Current code.
[capital-apms.git] / rb / APMS / SqlStore.rb
blob69adaa17c4321962c0e5ab271596fdeb6832a5e8
2 # == SqlStore
3 # A class including Gtk::TreeModel which contains a result set from an SQL Statement
5 # == Bugs
6 # Perish the thought!  Those are _features_!
8 # == Author
9 # Andrew McMillan <andrew@mcmillan.net.nz>
11 # == License
12 # Copyright (c) Andrew McMillan, 2007
13 # GNU General Public License version 2
17 class SqlStore
19   include Gtk::TreeModel
21   def initialize( file_name )
22     @sql = ""
23     @size_x = 600
24     @size_y = 100
25   end
27   def parse_definition( file_name )
28     state = false
29     File.foreach(filename) do |ln|
31       if !state then
32         if ln.match( /^([A-Z]+):\s*(#.*)?$/ )
33           state = $1
34         elsif ln.match( /^\s*(\S+)(:\S+)?\s*=\s*(\S.*\S?)\s*$/ ) then
35           case $1
36             when "X"
37               @size_x = $3.to_i if ( $3.to_i > 100)
39             when "Y"
40               @size_y = $3.to_i if ( $3.to_i > 100)
41           end
42         end
43         next
44       end
46       puts "State: '#{state}', Line: '#{ln.chomp}'"
48       if ln.match( /^:#{state}$/ ) then
49         state = false
50         next
51       end
53       case state
54         when "FIELDS"
55           if ln.match( /^\s*(\S+)(:\S+)?\s*=\s*(\S.*\S?)\s*$/ ) then
56             @fields.set($1, $2, $3 )
57           end
59         when "SQL"
60           @sql += ln
62         when "KEYS"
63           if ln.match( /^\s*(\S+)\s*=\s*(\S.*\S?)\s*$/ ) then
64             @keys[$1] = $2.split(/\s*,\s*/)
65           end
67       end
69     end
70   end
72 end
97 # A basic field in an ApmsRecordBrowser
98 class ApmsField
100   attr_reader :name, :heading, :type, :position
101   attr_writer :heading, :type, :position
103   def initialize(in_name)
104     @name = in_name
105     @heading = in_name
106     @type = "Text"
107     @position = nil
108     puts " New field '#{in_name}'"
109   end
111   def set( what, value )
112     case what
113       when 'heading', '', nil
114         @heading = value
115         puts "#{@name} heading set to '#{@heading}'"
116       when 'type'
117         @type = value
118         puts "#{@name} type set to '#{@type}'"
119     end
120   end
124 # Hash of ApmsField objects which is keyed on the field name
125 class ApmsFieldList
126   def initialize
127     @fields = Hash.new
128     @positions = Array.new
129   end
131   def size
132     return @positions.size
133   end
135   def fields
136     return @fields
137   end
139   def positions
140     return @positions
141   end
143   def each_field
144     @positions.each_index do |idx|
145       yield idx, @positions[idx], @fields[@positions[idx]]
146     end
147   end
149   def set( name, what, value )
150 #    puts " Setting '#{what}' to '#{value}' in field '#{name}' "
151     if ( @fields[name] == nil ) then
152       @fields[name] = ApmsField.new(name)
153       @positions.push(name)
154       @fields[name].position = @positions.size
155     end
156     @fields[name].set(what,value)
157   end
160 class ApmsRecordBrowser
162   #
163   # Creates an empty record browser with no columns and no rows, based on
164   # Gtk::TreeView.  This class adds some utility functionality to load
165   # the definition of the browser widget from a file.
166   #
167   def columns=(col_name_hash)
168     set_columns(col_name_hash)
169   end
171   attr_reader :columns, :treeview, :size_x, :size_y
173   def initialize(path)
174     @fields = ApmsFieldList.new
175     @treeview = Gtk::TreeView.new
176     @liststore = Gtk::ListStore.new(String,String,String,String,String,String,String,String)
177     load_browse_definition(path)
178     @treeview.set_model(@liststore)
179     @treeview.set_size_request(@size_x, @size_y)
180     @treeview.set_headers_clickable(true)
181     @treeview.set_enable_search(true)
182     @treeview.set_rules_hint(true)
184 #    @treeview.signal_connect("event") do |w,e|
185 #      if e.event_type != Gdk::Event::MOTION_NOTIFY then
186 #        puts "Got event #{e} - '#{e.event_type.inspect}'"
187 #        puts e.inspect
188 #      end
189 #    end
191 #    @treeview.signal_connect("key-release-event") do |w,e|
192 #      puts "Got key-release event #{e} - '#{e.event_type.inspect}'"
193 #      puts e.inspect
194 #    end
196   end
198   def apply_fields
199     n_columns = @fields.size
200     @fields.each_field do |position,field,value|
201       @treeview.append_column(Gtk::TreeViewColumn.new(value.heading, Gtk::CellRendererText.new, {:text => position} ))
202     end
203   end
205   # This does kind of depend on the SQL returning the columns as named in the
206   # call to set_columns
207   def set_data( sql )
208     puts "SQL is: #{sql}"
209     rows_sth = $dbh.prepare(sql)
210     rows_sth.execute()
212     rows_sth.each do |row|
213       values = @liststore.append
214       @fields.each_field do |position,field,value|
215         values.set_value(position,row[field])
216       end
217     end
218   end
220   #
221   # Read the definitions of this browse window from a file
222   #
223   def load_browse_definition( filename )
225     apply_fields
226     set_data( @sql )
228   end
230   def selection
231     return @treeview.selection
232   end
234   def get_key( key_name )
235     iter = @treeview.selection
236     key = Array.new
237     @keys[key_name].each_index do |fieldname|
238       key.push( iter[@fields.fields[fieldname].position] )
239     end
240   end