* Added command line tool example similar to 'sopranocmd'
[kdebindings.git] / ruby / qtruby / rails_support / active_item_model.rb
blobca2c3ede46afa94ab4a370c8e4ce12b34f1b7c5f
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
111     def [](row)
112         row = row.row if row.is_a?Qt::ModelIndex
113         @collection[row]
114     end
116     def column(name)
117         @keys.index name
118     end
119     
120     def columnCount(parent)
121         if parent.valid?
122             return parent.internalPointer.columnCount
123         else
124             return @rootItem.columnCount
125         end
126     end
127     
128     def data(index, role)
129         if !index.valid?
130             return Qt::Variant.new
131         end
132     
133         if role != Qt::DisplayRole
134             return Qt::Variant.new
135         end
136     
137         item = index.internalPointer
138         return item.data(index.column)
139     end
141     def setData(index, variant, role=Qt::EditRole)
142         if index.valid? and role == Qt::EditRole
143             raise "invalid column #{index.column}" if (index.column < 0 ||
144                 index.column >= @keys.size)
146             att = @keys[index.column]
147             item = index.internalPointer
149             if ! item.itemData.has_key? att
150                 return false
151             end
153             value = variant.value
155             if value.class.name == "Qt::Date"
156                 value = Date.new(value.year, value.month, value.day)
157             elsif value.class.name == "Qt::Time"
158                 value = Time.new(value.hour, value.min, value.sec)
159             end
161             att.gsub!(/.*\.(.*)/, '\1')
162             # Don't allow the primary key to be changed
163             if att == 'id'
164                 return false
165             end
167             eval("item.resource.attributes['%s'] = value" % att)
168             item.resource.save
169             emit dataChanged(index, index)
170             return true
171         else
172             return false
173         end
174     end
175     
176     def flags(index)
177         if !index.valid?
178             return Qt::ItemIsEnabled
179         end
180     
181         return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable
182     end
183     
184     def headerData(section, orientation, role)
185         if orientation == Qt::Horizontal && role == Qt::DisplayRole
186             return Qt::Variant.new(@labels[@keys[section]])
187         end
188     
189         return Qt::Variant.new
190     end
191     
192     def index(row, column, parent)
193         if !parent.valid?
194             parentItem = @rootItem
195         else
196             parentItem = parent.internalPointer
197         end
198     
199         @childItem = parentItem.child(row)
200         if ! @childItem.nil?
201             return createIndex(row, column, @childItem)
202         else
203             return Qt::ModelIndex.new
204         end
205     end
206     
207     def parent(index)
208         if !index.valid?
209             return Qt::ModelIndex.new
210         end
211     
212         childItem = index.internalPointer
213         parentItem = childItem.parent
214     
215         if parentItem == @rootItem
216             return Qt::ModelIndex.new
217         end
218     
219         return createIndex(parentItem.row, 0, parentItem)
220     end
221     
222     def rowCount(parent)
223         if !parent.valid?
224             parentItem = @rootItem
225         else
226             parentItem = parent.internalPointer
227         end
228     
229         return parentItem.childCount
230     end
233 # kate: indent-width 4;