clevic 0.13.0.b9 → 0.13.0.b10
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/lib/clevic/action_builder.rb +16 -16
- data/lib/clevic/ar_methods.rb +22 -22
- data/lib/clevic/attribute_list.rb +5 -5
- data/lib/clevic/cache_table.rb +18 -18
- data/lib/clevic/dataset_roller.rb +3 -3
- data/lib/clevic/default_view.rb +4 -4
- data/lib/clevic/delegate.rb +8 -8
- data/lib/clevic/delegates/combo_delegate.rb +22 -22
- data/lib/clevic/delegates/distinct_delegate.rb +5 -5
- data/lib/clevic/delegates/relational_delegate.rb +6 -6
- data/lib/clevic/delegates/set_delegate.rb +3 -3
- data/lib/clevic/dirty.rb +1 -1
- data/lib/clevic/emitter.rb +3 -3
- data/lib/clevic/extensions.rb +4 -4
- data/lib/clevic/field.rb +68 -68
- data/lib/clevic/field_valuer.rb +26 -26
- data/lib/clevic/filter_command.rb +6 -6
- data/lib/clevic/framework.rb +3 -3
- data/lib/clevic/generic_format.rb +2 -2
- data/lib/clevic/many_field.rb +3 -3
- data/lib/clevic/model_builder.rb +88 -84
- data/lib/clevic/model_column.rb +13 -13
- data/lib/clevic/ordered_dataset.rb +7 -7
- data/lib/clevic/qt/action_builder.rb +3 -3
- data/lib/clevic/qt/browser.rb +28 -28
- data/lib/clevic/qt/clipboard.rb +5 -5
- data/lib/clevic/qt/combo_delegate.rb +12 -12
- data/lib/clevic/qt/distinct_delegate.rb +1 -1
- data/lib/clevic/qt/extensions.rb +4 -4
- data/lib/clevic/qt/qt_combo_box.rb +7 -7
- data/lib/clevic/qt/relational_delegate.rb +5 -5
- data/lib/clevic/qt/search_dialog.rb +15 -15
- data/lib/clevic/qt/simplest_delegate.rb +2 -2
- data/lib/clevic/qt/table_model.rb +46 -46
- data/lib/clevic/qt/table_view.rb +48 -48
- data/lib/clevic/qt/text_delegate.rb +9 -9
- data/lib/clevic/rails_models_loaders.rb +3 -3
- data/lib/clevic/record.rb +8 -8
- data/lib/clevic/sampler.rb +6 -6
- data/lib/clevic/sequel_ar_adapter.rb +22 -22
- data/lib/clevic/sequel_clevic.rb +10 -10
- data/lib/clevic/sequel_meta.rb +5 -5
- data/lib/clevic/sequel_naked.rb +4 -4
- data/lib/clevic/swing/action.rb +20 -20
- data/lib/clevic/swing/action_builder.rb +2 -2
- data/lib/clevic/swing/boolean_delegate.rb +3 -3
- data/lib/clevic/swing/browser.rb +37 -37
- data/lib/clevic/swing/cell_editor.rb +13 -13
- data/lib/clevic/swing/cell_renderer.rb +7 -7
- data/lib/clevic/swing/clipboard.rb +19 -19
- data/lib/clevic/swing/combo_delegate.rb +26 -26
- data/lib/clevic/swing/confirm_dialog.rb +7 -7
- data/lib/clevic/swing/delegate.rb +4 -4
- data/lib/clevic/swing/extensions.rb +24 -24
- data/lib/clevic/swing/field.rb +1 -1
- data/lib/clevic/swing/relational_delegate.rb +2 -2
- data/lib/clevic/swing/row_header.rb +32 -32
- data/lib/clevic/swing/search_dialog.rb +31 -31
- data/lib/clevic/swing/selection_model.rb +12 -12
- data/lib/clevic/swing/swing_table_index.rb +6 -6
- data/lib/clevic/swing/table_model.rb +30 -30
- data/lib/clevic/swing/table_view.rb +54 -54
- data/lib/clevic/swing/table_view_focus.rb +4 -4
- data/lib/clevic/swing/tag_delegate.rb +14 -14
- data/lib/clevic/swing/tag_editor.rb +4 -4
- data/lib/clevic/swing/text_area_delegate.rb +6 -6
- data/lib/clevic/swing/text_delegate.rb +4 -4
- data/lib/clevic/table_index.rb +14 -14
- data/lib/clevic/table_model.rb +30 -30
- data/lib/clevic/table_searcher.rb +19 -19
- data/lib/clevic/table_view.rb +92 -92
- data/lib/clevic/table_view_paste.rb +19 -19
- data/lib/clevic/version.rb +1 -1
- data/lib/clevic/view.rb +22 -22
- data/models/accounts_models.rb +10 -10
- data/models/examples.rb +2 -2
- data/models/times_models.rb +32 -32
- data/models/values_models.rb +2 -2
- data/test/test_cache_table.rb +15 -15
- data/test/test_helper.rb +7 -7
- data/test/test_model_index_extensions.rb +6 -6
- data/test/test_table_model.rb +6 -6
- data/test/test_table_searcher.rb +25 -25
- metadata +33 -35
data/lib/clevic/table_view.rb
CHANGED
@@ -14,15 +14,15 @@ module Clevic
|
|
14
14
|
# Various methods common to view classes
|
15
15
|
class TableView
|
16
16
|
include ActionBuilder
|
17
|
-
|
17
|
+
|
18
18
|
# the current stack of filter commands
|
19
19
|
def filters
|
20
20
|
@filtered ||= []
|
21
21
|
end
|
22
22
|
attr_writer :filters
|
23
|
-
|
23
|
+
|
24
24
|
def filtered?; !filters.empty?; end
|
25
|
-
|
25
|
+
|
26
26
|
# Called from the gui-framework adapter code in this class
|
27
27
|
# arg is:
|
28
28
|
# - an instance of Clevic::View
|
@@ -33,42 +33,42 @@ class TableView
|
|
33
33
|
when arg.is_a?( TableModel )
|
34
34
|
self.model = arg
|
35
35
|
init_actions( arg.entity_view )
|
36
|
-
|
36
|
+
|
37
37
|
when arg.is_a?( Clevic::View )
|
38
38
|
model_builder = arg.define_ui
|
39
39
|
model_builder.exec_ui_block( &block )
|
40
|
-
|
40
|
+
|
41
41
|
# make sure the TableView has a fully-populated TableModel
|
42
42
|
# self.model is necessary to invoke the GUI layer
|
43
43
|
self.model = model_builder.build( self )
|
44
44
|
self.object_name = arg.widget_name
|
45
|
-
|
45
|
+
|
46
46
|
# connect data_changed signals for the entity_class to respond
|
47
47
|
connect_view_signals( arg )
|
48
|
-
|
48
|
+
|
49
49
|
init_actions( arg )
|
50
|
-
|
50
|
+
|
51
51
|
else
|
52
52
|
raise "Don't know what to do with #{arg.inspect}"
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
attr_accessor :object_name
|
57
|
-
|
57
|
+
|
58
58
|
def title
|
59
59
|
@title ||= model.entity_view.title
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
# find the row index for the given field id (symbol)
|
63
63
|
def field_column( field )
|
64
64
|
raise "use model.field_column( field )"
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
# return menu actions for the model, or an empty array if there aren't any
|
68
68
|
def model_actions
|
69
69
|
@model_actions ||= []
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
# hook for the sanity_check_xxx methods
|
73
73
|
# called for the actions set up by ActionBuilder
|
74
74
|
# it just wraps the action block/method in a catch
|
@@ -78,14 +78,14 @@ class TableView
|
|
78
78
|
catch :insane do
|
79
79
|
yield
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
rescue Exception => e
|
83
83
|
puts
|
84
84
|
puts "#{model.entity_view.class.name}: #{e.message}"
|
85
85
|
puts e.backtrace
|
86
86
|
end
|
87
|
-
|
88
|
-
|
87
|
+
|
88
|
+
|
89
89
|
# called from framework_init
|
90
90
|
def init_actions( entity_view )
|
91
91
|
# add model actions, if they're defined
|
@@ -93,7 +93,7 @@ class TableView
|
|
93
93
|
entity_view.define_actions( self, ab )
|
94
94
|
separator unless collect_actions.empty?
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
# list of actions in the edit menu
|
98
98
|
list( :edit ) do
|
99
99
|
action :action_save, '&Save', :shortcut => 'Ctrl+S', :method => :save_current_rows
|
@@ -111,16 +111,16 @@ class TableView
|
|
111
111
|
action :action_row, 'New Ro&w', :shortcut => 'Ctrl+N', :method => :new_row
|
112
112
|
action :action_refresh, '&Refresh', :shortcut => 'Ctrl+R', :method => :refresh
|
113
113
|
action :action_delete_rows, 'Delete Rows', :shortcut => 'Ctrl+Delete', :method => :delete_rows
|
114
|
-
|
114
|
+
|
115
115
|
if $options[:debug]
|
116
116
|
action :action_dump, 'Du&mp', :shortcut => 'Ctrl+Shift+D' do
|
117
117
|
puts model.collection[current_index.row].inspect
|
118
118
|
end
|
119
119
|
end
|
120
120
|
end
|
121
|
-
|
121
|
+
|
122
122
|
separator
|
123
|
-
|
123
|
+
|
124
124
|
# list of actions for search
|
125
125
|
list( :search ) do
|
126
126
|
action :action_find, '&Find', :shortcut => 'Ctrl+F', :method => :find
|
@@ -130,7 +130,7 @@ class TableView
|
|
130
130
|
#~ action :action_highlight, '&Highlight', :visible => false, :shortcut => 'Ctrl+H'
|
131
131
|
end
|
132
132
|
end
|
133
|
-
|
133
|
+
|
134
134
|
def clipboard
|
135
135
|
# Clipboard will be a framework-specific class
|
136
136
|
@clipboard = Clipboard.new
|
@@ -141,7 +141,7 @@ class TableView
|
|
141
141
|
def copy_current_selection
|
142
142
|
clipboard.text = current_selection_csv
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
# return the current selection as csv
|
146
146
|
def current_selection_csv
|
147
147
|
buffer = StringIO.new
|
@@ -150,14 +150,14 @@ class TableView
|
|
150
150
|
end
|
151
151
|
buffer.string
|
152
152
|
end
|
153
|
-
|
153
|
+
|
154
154
|
def sanity_check_ditto
|
155
155
|
if current_index.row == 0
|
156
156
|
emit_status_text( 'No previous record to copy.' )
|
157
157
|
throw :insane
|
158
158
|
end
|
159
159
|
end
|
160
|
-
|
160
|
+
|
161
161
|
def sanity_check_read_only
|
162
162
|
if current_index.field.read_only?
|
163
163
|
emit_status_text( 'Can\'t copy into read-only field.' )
|
@@ -169,14 +169,14 @@ class TableView
|
|
169
169
|
end
|
170
170
|
throw :insane
|
171
171
|
end
|
172
|
-
|
172
|
+
|
173
173
|
def sanity_check_read_only_table
|
174
174
|
if model.read_only?
|
175
175
|
emit_status_text( 'Can\'t modify a read-only table.' )
|
176
176
|
throw :insane
|
177
177
|
end
|
178
178
|
end
|
179
|
-
|
179
|
+
|
180
180
|
def ditto
|
181
181
|
sanity_check_ditto
|
182
182
|
sanity_check_read_only
|
@@ -189,7 +189,7 @@ class TableView
|
|
189
189
|
end
|
190
190
|
end
|
191
191
|
end
|
192
|
-
|
192
|
+
|
193
193
|
# from and to are ModelIndex instances. Throws :insane if
|
194
194
|
# their fields don't have the same attribute_type.
|
195
195
|
def sanity_check_types( from, to )
|
@@ -198,7 +198,7 @@ class TableView
|
|
198
198
|
throw :insane
|
199
199
|
end
|
200
200
|
end
|
201
|
-
|
201
|
+
|
202
202
|
def ditto_right
|
203
203
|
sanity_check_ditto
|
204
204
|
sanity_check_read_only
|
@@ -211,7 +211,7 @@ class TableView
|
|
211
211
|
model.data_changed( current_index )
|
212
212
|
end
|
213
213
|
end
|
214
|
-
|
214
|
+
|
215
215
|
def ditto_left
|
216
216
|
sanity_check_ditto
|
217
217
|
sanity_check_read_only
|
@@ -224,22 +224,22 @@ class TableView
|
|
224
224
|
model.data_changed( current_index )
|
225
225
|
end
|
226
226
|
end
|
227
|
-
|
227
|
+
|
228
228
|
def insert_current_date
|
229
229
|
sanity_check_read_only
|
230
230
|
current_index.attribute_value = Time.now
|
231
231
|
model.data_changed( current_index )
|
232
232
|
end
|
233
|
-
|
233
|
+
|
234
234
|
def open_editor
|
235
235
|
# tell the table to edit here
|
236
236
|
edit( current_index )
|
237
|
-
|
237
|
+
|
238
238
|
# tell the editing component to do full edit, eg if it's a combo
|
239
239
|
# box to open the list.
|
240
240
|
current_index.field.delegate.full_edit
|
241
241
|
end
|
242
|
-
|
242
|
+
|
243
243
|
# Add a new row and move to it, provided we're not in a read-only view.
|
244
244
|
def new_row
|
245
245
|
sanity_check_read_only_table
|
@@ -247,7 +247,7 @@ class TableView
|
|
247
247
|
selection_model.clear
|
248
248
|
self.current_index = model.create_index( model.row_count - 1, 0 )
|
249
249
|
end
|
250
|
-
|
250
|
+
|
251
251
|
# Delete the current selection. If it's a set of rows, just delete
|
252
252
|
# them. If it's a rectangular selection, set the cells to nil.
|
253
253
|
# TODO make sure all affected rows are saved.
|
@@ -255,7 +255,7 @@ class TableView
|
|
255
255
|
busy_cursor do
|
256
256
|
begin
|
257
257
|
sanity_check_read_only
|
258
|
-
|
258
|
+
|
259
259
|
# TODO translate from ModelIndex objects to row indices
|
260
260
|
puts "#{__FILE__}:#{__LINE__}:implement vertical_header for delete_selection"
|
261
261
|
#~ rows = vertical_header.selection_model.selected_rows.map{|x| x.row}
|
@@ -272,15 +272,15 @@ class TableView
|
|
272
272
|
end
|
273
273
|
end
|
274
274
|
end
|
275
|
-
|
275
|
+
|
276
276
|
def search_dialog
|
277
277
|
@search_dialog ||= SearchDialog.new( self )
|
278
278
|
end
|
279
|
-
|
279
|
+
|
280
280
|
# display a search dialog, and find the entered text
|
281
281
|
def find
|
282
282
|
result = search_dialog.exec( current_index.display_value )
|
283
|
-
|
283
|
+
|
284
284
|
busy_cursor do
|
285
285
|
case
|
286
286
|
when result.accepted?
|
@@ -292,7 +292,7 @@ class TableView
|
|
292
292
|
end
|
293
293
|
end
|
294
294
|
end
|
295
|
-
|
295
|
+
|
296
296
|
def find_next
|
297
297
|
# yes, this must be an @ otherwise it lazy-creates
|
298
298
|
# and will never be nil
|
@@ -307,7 +307,7 @@ class TableView
|
|
307
307
|
end
|
308
308
|
end
|
309
309
|
end
|
310
|
-
|
310
|
+
|
311
311
|
# force a complete reload of the current tab's data
|
312
312
|
def refresh
|
313
313
|
busy_cursor do
|
@@ -316,27 +316,27 @@ class TableView
|
|
316
316
|
end
|
317
317
|
end
|
318
318
|
end
|
319
|
-
|
319
|
+
|
320
320
|
# return an array of the current selection, or the
|
321
321
|
# current index in an array if the selection is empty
|
322
322
|
def selection_or_current
|
323
323
|
indexes_or_current( selection_model.selected_indexes )
|
324
324
|
end
|
325
|
-
|
325
|
+
|
326
326
|
def selected_rows_or_current
|
327
327
|
indexes_or_current( selection_model.row_indexes.map{|row| model.create_index( row, 0 ) } )
|
328
328
|
end
|
329
|
-
|
329
|
+
|
330
330
|
# alternative access for auto_size_column
|
331
331
|
def auto_size_attribute( attribute, sample )
|
332
332
|
auto_size_column( model.attributes.index( attribute ), sample )
|
333
333
|
end
|
334
|
-
|
334
|
+
|
335
335
|
# is current_index on the last row?
|
336
336
|
def last_row?
|
337
337
|
current_index.row == model.row_count - 1
|
338
338
|
end
|
339
|
-
|
339
|
+
|
340
340
|
# is current_index on the bottom_right cell?
|
341
341
|
def last_cell?
|
342
342
|
current_index.row == model.row_count - 1 && current_index.column == model.column_count - 1
|
@@ -349,7 +349,7 @@ class TableView
|
|
349
349
|
auto_size_column( index, field.sample )
|
350
350
|
end
|
351
351
|
end
|
352
|
-
|
352
|
+
|
353
353
|
# copied from actionpack
|
354
354
|
def pluralize(count, singular, plural = nil)
|
355
355
|
"#{count || 0} " + ((count == 1 || count == '1') ? singular : (plural || singular.pluralize))
|
@@ -358,7 +358,7 @@ class TableView
|
|
358
358
|
# ask the question in a dialog. If the user says yes, execute the block
|
359
359
|
def delete_multiple_cells?( question = 'Are you sure you want to delete multiple cells?', &block )
|
360
360
|
sanity_check_read_only
|
361
|
-
|
361
|
+
|
362
362
|
# go ahead with delete if there's only 1 cell, or the user says OK
|
363
363
|
delete_ok =
|
364
364
|
if selection_model.selected_indexes.size > 1
|
@@ -366,29 +366,29 @@ class TableView
|
|
366
366
|
else
|
367
367
|
true
|
368
368
|
end
|
369
|
-
|
369
|
+
|
370
370
|
yield if delete_ok
|
371
371
|
end
|
372
|
-
|
372
|
+
|
373
373
|
# Ask if multiple cell delete is OK, then replace contents
|
374
374
|
# of selected cells with nil.
|
375
375
|
def delete_cells
|
376
376
|
delete_multiple_cells? do
|
377
377
|
cells_deleted = false
|
378
|
-
|
378
|
+
|
379
379
|
# do delete
|
380
380
|
selection_model.selected_indexes.each do |index|
|
381
381
|
index.attribute_value = nil
|
382
382
|
cells_deleted = true
|
383
383
|
end
|
384
|
-
|
384
|
+
|
385
385
|
# deletes were done, so call data_changed
|
386
386
|
if cells_deleted
|
387
387
|
# save affected rows
|
388
388
|
selection_model.row_indexes.each do |row_index|
|
389
389
|
save_row( model.create_index( row_index, 0 ) )
|
390
390
|
end
|
391
|
-
|
391
|
+
|
392
392
|
# emit data changed for all ranges
|
393
393
|
selection_model.ranges.each do |selection_range|
|
394
394
|
model.data_changed( selection_range )
|
@@ -396,7 +396,7 @@ class TableView
|
|
396
396
|
end
|
397
397
|
end
|
398
398
|
end
|
399
|
-
|
399
|
+
|
400
400
|
def delete_rows
|
401
401
|
delete_multiple_cells?( "Are you sure you want to delete #{selection_model.row_indexes.size} rows?" ) do
|
402
402
|
begin
|
@@ -408,7 +408,7 @@ class TableView
|
|
408
408
|
end
|
409
409
|
end
|
410
410
|
end
|
411
|
-
|
411
|
+
|
412
412
|
# handle certain key combinations that aren't shortcuts
|
413
413
|
# TODO what is returned from here?
|
414
414
|
def handle_key_press( event )
|
@@ -421,7 +421,7 @@ class TableView
|
|
421
421
|
puts e.backtrace
|
422
422
|
show_error( "Error in shortcut handler for #{model.entity_view.name}: #{e.message}" )
|
423
423
|
end
|
424
|
-
|
424
|
+
|
425
425
|
# thrown by the sanity_check_xxx methods
|
426
426
|
catch :insane do
|
427
427
|
case
|
@@ -429,17 +429,17 @@ class TableView
|
|
429
429
|
# add a new row
|
430
430
|
when event.down? && last_row?
|
431
431
|
new_row
|
432
|
-
|
432
|
+
|
433
433
|
# on the right-bottom cell, and tab is pressed
|
434
434
|
# then add a new row
|
435
435
|
when event.tab? && last_cell?
|
436
436
|
new_row
|
437
|
-
|
437
|
+
|
438
438
|
# add new record and go to it
|
439
439
|
# TODO this is actually a shortcut
|
440
440
|
when event.ctrl? && event.return?
|
441
441
|
new_row
|
442
|
-
|
442
|
+
|
443
443
|
else
|
444
444
|
#~ puts event.inspect
|
445
445
|
end
|
@@ -450,13 +450,13 @@ class TableView
|
|
450
450
|
show_error( "handle_key_press #{__FILE__}:#{__LINE__} error in #{current_index.attribute.to_s}: \"#{e.message}\"" )
|
451
451
|
end
|
452
452
|
end
|
453
|
-
|
453
|
+
|
454
454
|
def save_current_rows
|
455
455
|
selection_model.row_indexes.each do |row_index|
|
456
456
|
save_row( model.create_index( row_index, 0 ) )
|
457
457
|
end
|
458
458
|
end
|
459
|
-
|
459
|
+
|
460
460
|
# save the entity in the row of the given index
|
461
461
|
# actually, model.save will check if the record
|
462
462
|
# is really changed before writing to DB.
|
@@ -469,13 +469,13 @@ class TableView
|
|
469
469
|
abbr_value = trim_middle( index.entity.send(field) )
|
470
470
|
"#{field} (#{abbr_value}) #{errors.join(',')}"
|
471
471
|
end.join( "\n" )
|
472
|
-
|
472
|
+
|
473
473
|
show_error( "Validation Errors: #{index.rc} #{msg}" )
|
474
474
|
end
|
475
475
|
saved
|
476
476
|
end
|
477
477
|
end
|
478
|
-
|
478
|
+
|
479
479
|
# save record whenever its row is exited
|
480
480
|
# make this work with framework
|
481
481
|
def currentChanged( current_index, previous_index )
|
@@ -485,22 +485,22 @@ class TableView
|
|
485
485
|
end
|
486
486
|
super
|
487
487
|
end
|
488
|
-
|
488
|
+
|
489
489
|
# toggle the filter, based on current selection.
|
490
490
|
def filter_by_current
|
491
491
|
filter_by_indexes( selection_or_current )
|
492
492
|
end
|
493
|
-
|
493
|
+
|
494
494
|
# This is used by entity view classes.
|
495
495
|
# Keep it as a compatibility / deprecated option?
|
496
496
|
def filter_by_options( args )
|
497
497
|
puts "#{self.class.name}#filter_by_options is deprecated. Use filter_by_dataset( message, &block ) instead."
|
498
|
-
|
498
|
+
|
499
499
|
filter_by_dataset( "#{args.inspect}" ) do |dataset|
|
500
500
|
dataset.translate( args )
|
501
501
|
end
|
502
502
|
end
|
503
|
-
|
503
|
+
|
504
504
|
# Save the current entity, do something, then restore
|
505
505
|
# the cursor position to the entity if possible.
|
506
506
|
# Return the result of the block.
|
@@ -510,26 +510,26 @@ class TableView
|
|
510
510
|
save_entity.save if save_entity.changed?
|
511
511
|
save_index = current_index
|
512
512
|
end
|
513
|
-
|
513
|
+
|
514
514
|
retval = yield
|
515
|
-
|
515
|
+
|
516
516
|
# find the entity if possible
|
517
517
|
select_entity( save_entity, save_index.column ) unless save_entity.nil?
|
518
|
-
|
518
|
+
|
519
519
|
retval
|
520
520
|
end
|
521
|
-
|
521
|
+
|
522
522
|
def unfilter
|
523
523
|
restore_entity do
|
524
524
|
filters.pop.undo
|
525
525
|
end
|
526
526
|
update_filter_status_bar
|
527
527
|
end
|
528
|
-
|
528
|
+
|
529
529
|
def unfilter_action
|
530
530
|
search_actions.find{|a| a.object_name == 'action_unfilter' }
|
531
531
|
end
|
532
|
-
|
532
|
+
|
533
533
|
def filter_message
|
534
534
|
"Filter: " + filters.map( &:message ).join(' / ') unless filters.empty?
|
535
535
|
end
|
@@ -540,34 +540,34 @@ class TableView
|
|
540
540
|
emit_filter_status( filtered? )
|
541
541
|
unfilter_action.enabled = filtered?
|
542
542
|
end
|
543
|
-
|
543
|
+
|
544
544
|
def filter_by_dataset( message = nil, &dataset_block )
|
545
545
|
# TODO clean this up and make it work AND for multiple columns, OR for multiple rows
|
546
546
|
self.filters << FilterCommand.new( self, message, &dataset_block )
|
547
|
-
|
547
|
+
|
548
548
|
# try to end up on the same entity, even after the filter
|
549
549
|
restore_entity { filters.last.doit }
|
550
|
-
|
550
|
+
|
551
551
|
# make sure status bar shows status
|
552
552
|
update_filter_status_bar
|
553
553
|
end
|
554
|
-
|
554
|
+
|
555
555
|
# Filter by the value in the current index.
|
556
556
|
# indexes is a collection of TableIndex instances
|
557
557
|
def filter_by_indexes( indexes )
|
558
558
|
case
|
559
559
|
when indexes.empty?
|
560
560
|
emit_status_text( "No field selected for filter" )
|
561
|
-
|
561
|
+
|
562
562
|
when !indexes.first.field.filterable?
|
563
563
|
emit_status_text( "Can't filter on #{indexes.first.field.label}" )
|
564
|
-
|
564
|
+
|
565
565
|
when indexes.size > 1
|
566
566
|
emit_status_text( "Can't do multiple selection filters yet" )
|
567
|
-
|
567
|
+
|
568
568
|
when indexes.first.entity.new_record?
|
569
569
|
emit_status_text( "Can't filter on a new row" )
|
570
|
-
|
570
|
+
|
571
571
|
else
|
572
572
|
message = "#{indexes.first.field_name} = #{indexes.first.display_value}"
|
573
573
|
filter_by_dataset( message ) do |dataset|
|
@@ -582,7 +582,7 @@ class TableView
|
|
582
582
|
end
|
583
583
|
filtered?
|
584
584
|
end
|
585
|
-
|
585
|
+
|
586
586
|
# Move to the row for the given entity and the given column.
|
587
587
|
# If column is a symbol,
|
588
588
|
# field_column will be called to find the integer index.
|
@@ -592,12 +592,12 @@ class TableView
|
|
592
592
|
unless entity.is_a?( model.entity_class )
|
593
593
|
raise "entity #{entity.class.name} does not match class #{model.entity_class.name}"
|
594
594
|
end
|
595
|
-
|
595
|
+
|
596
596
|
# find the row for the saved entity
|
597
597
|
found_row = busy_cursor do
|
598
598
|
model.collection.index_for_entity( entity )
|
599
599
|
end
|
600
|
-
|
600
|
+
|
601
601
|
# create a new index and move to it
|
602
602
|
unless found_row.nil?
|
603
603
|
if column.is_a? Symbol
|
@@ -611,7 +611,7 @@ class TableView
|
|
611
611
|
self.current_index = model.create_index( found_row, column || 0 )
|
612
612
|
end
|
613
613
|
end
|
614
|
-
|
614
|
+
|
615
615
|
# search_criteria must respond to:
|
616
616
|
# * search_text
|
617
617
|
# * whole_words?
|
@@ -633,19 +633,19 @@ class TableView
|
|
633
633
|
# TODO doesn't really belong here because TableView will not always
|
634
634
|
# be in a TabWidget context.
|
635
635
|
framework_responsibility :find_table_view
|
636
|
-
|
636
|
+
|
637
637
|
# execute the block with the TableView instance
|
638
638
|
# currently handling the entity_model_or_view.
|
639
639
|
# Don't execute the block if nothing is found.
|
640
640
|
# TODO doesn't really belong here because TableView will not always
|
641
641
|
# be in a TabWidget context.
|
642
642
|
framework_responsibility :with_table_view
|
643
|
-
|
643
|
+
|
644
644
|
# make this window visible if it's in a TabWidget
|
645
645
|
# TODO doesn't really belong here because TableView will not always
|
646
646
|
# be in a TabWidget context.
|
647
647
|
framework_responsibility :raise_widget
|
648
|
-
|
648
|
+
|
649
649
|
# set next_index for certain operations. Is only activated when
|
650
650
|
# to_next_index is called.
|
651
651
|
attr_accessor :next_index
|
@@ -657,20 +657,20 @@ class TableView
|
|
657
657
|
def override_next_index( model_index )
|
658
658
|
self.next_index = model_index
|
659
659
|
end
|
660
|
-
|
660
|
+
|
661
661
|
# Call set_current_index with next_index ( from override_next_index )
|
662
662
|
# or model_index, in that order. Set next_index to nil afterwards.
|
663
663
|
def set_current_unless_override( model_index )
|
664
664
|
set_current_index( @next_index || model_index )
|
665
665
|
self.next_index = nil
|
666
666
|
end
|
667
|
-
|
667
|
+
|
668
668
|
protected
|
669
|
-
|
669
|
+
|
670
670
|
# Show a busy cursor, do the block, back to normal cursor
|
671
671
|
# return value of block
|
672
672
|
framework_responsibility :busy_cursor
|
673
|
-
|
673
|
+
|
674
674
|
# return either the set of indexes with all invalid indexes
|
675
675
|
# remove, or the current selection.
|
676
676
|
def indexes_or_current( indexes )
|
@@ -680,7 +680,7 @@ protected
|
|
680
680
|
else
|
681
681
|
indexes
|
682
682
|
end
|
683
|
-
|
683
|
+
|
684
684
|
# strip out bad indexes, so other things don't have to check
|
685
685
|
# can't use select because copying indexes causes an abort
|
686
686
|
# ie retval.select{|x| x != nil && x.valid?}
|