clevic 0.13.0.b9 → 0.13.0.b10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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?}
|