Module: Knj::Gtk2::Tv

Defined in:
lib/knj/gtk2_tv.rb

Overview

This module contains various helper-methods for handeling stuff regarding treeviews.

Constant Summary collapse

@@editable_text_callbacks =
{
  :datetime => {
    :value => proc{ |data|
      begin
        Datet.in(data[:value]).dbstr
      rescue ArgumentError
        raise "Invalid timestamp entered."
      end
    },
    :value_set => proc{ |data|
      Datet.in(data[:value]).out
    }
  },
  :time_as_sec => {
    :value => proc{ |data| Knj::Strings.human_time_str_to_secs(data[:value]) },
    :value_set => proc{ |data| Knj::Strings.secs_to_human_time_str(data[:value]) }
  },
  :int => {
    :value => proc{ |data| data[:value].to_i.to_s }
  },
  :human_number => {
    :value => proc{ |data| Knj::Locales.number_in(data[:value]) },
    :value_set => proc{ |data| Knj::Locales.number_out(data[:value], data[:col_data][:decimals]) }
  }
}

Class Method Summary collapse

Class Method Details

.append(tv, data) ⇒ Object

Appends data to the treeview.

Examples

Knj::Gtk2::Tv.append(treeview, [1, “Kasper”])



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/knj/gtk2_tv.rb', line 84

def self.append(tv, data)
  iter = tv.model.append
  
  count = 0
  data.each do |value|
    col = tv.columns[count]
    renderer = col.cell_renderers.first
    
    if renderer.is_a?(Gtk::CellRendererText)
      iter[count] = value.to_s
    elsif renderer.is_a?(Gtk::CellRendererToggle)
      iter[count] = Knj::Strings.yn_str(value, 1, 0)
    elsif renderer.is_a?(Gtk::CellRendererCombo)
      iter[count] = value.to_s
    else
      raise "Unknown renderer: '#{renderer.class.name}'."
    end
    
    count += 1
  end
  
  return {:iter => iter}
end

.editable_text_renderers_to_model(args) ⇒ Object



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/knj/gtk2_tv.rb', line 154

def self.editable_text_renderers_to_model(args)
  args[:id_col] = 0 if !args.key?(:id_col)
  
  args[:cols].each do |col_no, col_data|
    col_data = {:col => col_data} if col_data.is_a?(Symbol)
    
    if col_data.key?(:type)
      if callbacks = @@editable_text_callbacks[col_data[:type]]
        col_data[:value_callback] = callbacks[:value] if callbacks.key?(:value)
        col_data[:value_set_callback] = callbacks[:value_set] if callbacks.key?(:value_set)
      else
        raise "Invalid type: '#{col_data[:type]}'."
      end
    end
    
    renderer = args[:renderers][col_no]
    
    if args[:on_edit]
      renderer.signal_connect("editing-started") do |renderer, row_no, path|
        iter = args[:tv].model.get_iter(path)
        id = args[:tv].model.get_value(iter, args[:id_col])
        model_obj = args[:ob].get(args[:model_class], id)
        
        args[:on_edit].call(:renderer => renderer, :row_no => row_no, :path => path, :args => args, :model => model_obj, :col_no => col_no, :col_data => col_data)
      end
    end
    
    if args[:on_edit_done]
      renderer.signal_connect("editing-canceled") do |renderer|
        args[:on_edit_done].call(:renderer => renderer, :done_mode => :canceled, :args => args, :col_no => col_no, :col_data => col_data)
      end
    end
    
    if renderer.is_a?(Gtk::CellRendererText)
      renderer.editable = true
      renderer.signal_connect("edited") do |renderer, row_no, value|
        iter = args[:tv].model.get_iter(row_no)
        id = args[:tv].model.get_value(iter, args[:id_col])
        model_obj = args[:ob].get(args[:model_class], id)
        cancel = false
        callback_hash = {:args => args, :value => value, :model => model_obj, :col_no => col_no, :col_data => col_data}
        
        if args[:on_edit_done]
          args[:on_edit_done].call(:renderer => renderer, :row_no => row_no, :done_mode => :canceled, :args => args, :model => model_obj, :col_no => col_no, :col_data => col_data)
        end
        
        if col_data[:value_callback]
          begin
            value = col_data[:value_callback].call(callback_hash)
            callback_hash[:value] = value
          rescue => e
            Knj::Gtk2.msgbox(e.message, "warning")
            cancel = true
          end
        end
        
        if !cancel
          begin
            args[:change_before].call(callback_hash) if args[:change_before]
          rescue => e
            cancel = true
            Knj::Gtk2.msgbox(e.message, "warning")
          end
          
          if !cancel
            begin
              model_obj[col_data[:col]] = value
              value = col_data[:value_set_callback].call(callback_hash) if col_data.key?(:value_set_callback)
              iter[col_no] = value
            rescue => e
              Knj::Gtk2.msgbox(e.message, "warning")
            ensure
              args[:change_after].call(callback_hash) if args[:change_after]
            end
          end
        end
      end
    elsif renderer.is_a?(Gtk::CellRendererToggle)
      renderer.activatable = true
      renderer.signal_connect("toggled") do |renderer, path, value|
        iter = args[:tv].model.get_iter(path)
        id = args[:tv].model.get_value(iter, 0)
        model_obj = args[:ob].get(args[:model_class], id)
        callback_hash = {:args => args, :value => value, :model => model_obj, :col_no => col_no, :col_data => col_data}
        
        if col_data[:value_callback]
          begin
            value = col_data[:value_callback].call(callback_hash)
            callback_hash[:value] = value
          rescue => e
            Knj::Gtk2.msgbox(e.message, "warning")
            cancel = true
          end
        end
        
        if !cancel
          args[:change_before].call(callback_hash) if args[:change_before]
          begin
            if model_obj[col_data[:col]].to_i == 1
              model_obj[col_data[:col]] = 0
              iter[col_no] = 0
            else
              model_obj[col_data[:col]] = 1
              iter[col_no] = 1
            end
          ensure
            args[:change_after].call(:args => args) if args[:change_after]
          end
        end
      end
    else
      raise "Invalid cellrenderer: '#{renderer.class.name}'."
    end
  end
end

.init(tv, columns) ⇒ Object

Initializes a treeview with a model and a number of columns. Returns a hash containing various data like the renderers.

Examples

Knj::Gtk2::Tv.init(treeview, [“ID”, “Name”])



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/knj/gtk2_tv.rb', line 6

def self.init(tv, columns)
  ret = {
    :renderers => []
  }
  
  model_args = []
  columns.each do |args|
    if args.is_a?(String)
      args = {:type => :string, :title => args}
    end
    
    if args[:type] == :string
      model_args << String
    elsif args[:type] == :toggle
      model_args << Integer
    elsif args[:type] == :combo
      model_args << String
    else
      raise "Invalid type: '#{args[:type]}'."
    end
  end
  
  list_store = Gtk::ListStore.new(*model_args)
  tv.model = list_store
  tv.reorderable = true
  
  count = 0
  columns.each do |args|
    if args.is_a?(String)
      args = {:type => :string, :title => args}
    end
    
    if args[:type] == :string
      if args[:markup]
        col_args = {:markup => count}
      else
        col_args = {:text => count}
      end
      
      renderer = Gtk::CellRendererText.new
      col = Gtk::TreeViewColumn.new(args[:title], renderer, col_args)
      col.resizable = true
      tv.append_column(col)
    elsif args[:type] == :toggle
      renderer = Gtk::CellRendererToggle.new
      col = Gtk::TreeViewColumn.new(args[:title], renderer, :active => count)
      tv.append_column(col)
    elsif args[:type] == :combo
      renderer = Gtk::CellRendererCombo.new
      renderer.text_column = 0
      
      if args[:markup]
        col_args = {:markup => count}
      else
        col_args = {:text => count}
      end
      
      col = Gtk::TreeViewColumn.new(args[:title], renderer, col_args)
      
      renderer.model = args[:model] if args.key?(:model)
      renderer.has_entry = args[:has_entry] if args.key?(:has_entry)
      tv.append_column(col)
    else
      raise "Invalid type: '#{args[:type]}'."
    end
    
    col.reorderable = true
    col.sort_column_id = count
    ret[:renderers] << renderer
    count += 1
  end
  
  return ret
end

.sel(tv) ⇒ Object

Gets the selected data from the treeview.

Examples

Knj::Gtk2::Tv.sel(treeview) #=> [1, “Kasper”]



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/knj/gtk2_tv.rb', line 111

def self.sel(tv)
  selected = tv.selection.selected_rows
  return nil if !tv.model or selected.size <= 0
  
  iter = tv.model.get_iter(selected[0])
  returnval = []
  columns = tv.columns
  
  count = 0
  columns.each do |column|
    returnval[count] = iter[count]
    count += 1
  end
  
  return returnval
end