clevic 0.13.0.b3 → 0.13.0.b5
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 +21 -0
- data/Manifest.txt +91 -85
- data/README.txt +33 -18
- data/Rakefile +2 -3
- data/TODO +8 -14
- data/bin/clevic +18 -20
- data/lib/clevic.rb +7 -1
- data/lib/clevic/action_builder.rb +4 -1
- data/lib/clevic/ar_methods.rb +72 -57
- data/lib/clevic/attribute_list.rb +4 -0
- data/lib/clevic/cache_table.rb +43 -69
- data/lib/clevic/dataset_roller.rb +22 -0
- data/lib/clevic/delegate.rb +11 -5
- data/lib/clevic/delegates/combo_delegate.rb +156 -0
- data/lib/clevic/delegates/distinct_delegate.rb +48 -0
- data/lib/clevic/delegates/relational_delegate.rb +59 -0
- data/lib/clevic/delegates/set_delegate.rb +31 -0
- data/lib/clevic/field.rb +39 -55
- data/lib/clevic/field_valuer.rb +23 -10
- data/lib/clevic/filter_command.rb +22 -36
- data/lib/clevic/framework.rb +37 -0
- data/lib/clevic/generic_format.rb +5 -1
- data/lib/clevic/many_field.rb +28 -3
- data/lib/clevic/model_builder.rb +27 -32
- data/lib/clevic/ordered_dataset.rb +45 -0
- data/lib/clevic/qt.rb +4 -1
- data/lib/clevic/qt/action_builder.rb +9 -1
- data/lib/clevic/qt/browser.rb +1 -1
- data/lib/clevic/qt/clipboard.rb +3 -3
- data/lib/clevic/qt/combo_delegate.rb +25 -89
- data/lib/clevic/qt/delegate.rb +25 -0
- data/lib/clevic/qt/distinct_delegate.rb +5 -23
- data/lib/clevic/qt/extensions.rb +8 -1
- data/lib/clevic/qt/qt_combo_box.rb +58 -0
- data/lib/clevic/qt/relational_delegate.rb +18 -58
- data/lib/clevic/qt/set_delegate.rb +4 -34
- data/lib/clevic/qt/simplest_delegate.rb +19 -0
- data/lib/clevic/qt/table_model.rb +10 -10
- data/lib/clevic/qt/table_view.rb +7 -23
- data/lib/clevic/qt/text_delegate.rb +2 -2
- data/lib/clevic/qt/ui/browser_ui.rb +1 -1
- data/lib/clevic/qt/ui/search_dialog_ui.rb +1 -1
- data/lib/clevic/rails_models_loaders.rb +13 -0
- data/lib/clevic/record.rb +2 -2
- data/lib/clevic/sampler.rb +85 -39
- data/lib/clevic/sequel_ar_adapter.rb +1 -28
- data/lib/clevic/sequel_clevic.rb +68 -0
- data/lib/clevic/sequel_meta.rb +1 -13
- data/lib/clevic/subclasses.rb +18 -0
- data/lib/clevic/swing.rb +2 -1
- data/lib/clevic/swing/action.rb +27 -3
- data/lib/clevic/swing/action_builder.rb +0 -2
- data/lib/clevic/swing/browser.rb +1 -10
- data/lib/clevic/swing/combo_delegate.rb +45 -133
- data/lib/clevic/swing/delegate.rb +2 -0
- data/lib/clevic/swing/distinct_delegate.rb +2 -14
- data/lib/clevic/swing/relational_delegate.rb +2 -20
- data/lib/clevic/swing/set_delegate.rb +13 -28
- data/lib/clevic/swing/table_view.rb +1 -1
- data/lib/clevic/table_model.rb +3 -4
- data/lib/clevic/table_searcher.rb +10 -31
- data/lib/clevic/table_view.rb +97 -43
- data/lib/clevic/ui/browser_ui.rb +133 -0
- data/lib/clevic/ui/search_dialog_ui.rb +106 -0
- data/lib/clevic/version.rb +2 -2
- data/models/accounts_models.rb +24 -21
- data/models/times_models.rb +34 -28
- data/models/times_psql_models.rb +9 -3
- data/models/times_sqlite_models.rb +24 -1
- data/sql/times_sqlite.sql +3 -3
- data/tasks/clevic.rake +2 -2
- data/test/test_cache_table.rb +9 -19
- data/test/test_table_searcher.rb +2 -5
- metadata +95 -91
- data/lib/clevic/order_attribute.rb +0 -63
- data/lib/clevic/qt/boolean_delegate.rb +0 -8
- data/lib/clevic/qt/delegates.rb +0 -1
- data/lib/clevic/qt/item_delegate.rb +0 -66
- data/lib/clevic/sql_dialects.rb +0 -33
- data/tasks/website.rake +0 -25
- data/test/test_order_attribute.rb +0 -62
- data/test/test_sql_dialects.rb +0 -77
@@ -0,0 +1,25 @@
|
|
1
|
+
module Clevic
|
2
|
+
|
3
|
+
class Delegate < Qt::ItemDelegate
|
4
|
+
# Figure out where to put the editor widget, taking into
|
5
|
+
# account the sizes of the headers
|
6
|
+
# TODO most of the subclasses are probably the same as this
|
7
|
+
def updateEditorGeometry( editor, style_option_view_item, model_index )
|
8
|
+
rect = style_option_view_item.rect
|
9
|
+
rect.set_width( [editor.size_hint.width,rect.width].max )
|
10
|
+
rect.set_height( editor.size_hint.height )
|
11
|
+
editor.set_geometry( rect )
|
12
|
+
end
|
13
|
+
|
14
|
+
# This catches the event that begins the edit process.
|
15
|
+
def editorEvent( event, model, style_option_view_item, model_index )
|
16
|
+
# See qt Clevic::TableView
|
17
|
+
parent.respond_to?( "before_edit_index=" ) && parent.before_edit_index = model_index
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'clevic/delegate'
|
@@ -1,35 +1,17 @@
|
|
1
1
|
require 'clevic/qt/combo_delegate.rb'
|
2
|
+
require 'clevic/qt/simplest_delegate.rb'
|
2
3
|
|
3
4
|
module Clevic
|
4
5
|
|
5
|
-
# Provide a list of all values in this field,
|
6
|
-
# and allow new values to be entered.
|
7
|
-
# :frequency can be set as an option. Boolean. If it's true
|
8
|
-
# the options are sorted in order of most frequently used first.
|
9
6
|
class DistinctDelegate < ComboDelegate
|
7
|
+
include SimplestDelegate
|
10
8
|
|
11
|
-
|
12
|
-
# works except when there is a '' in the column
|
13
|
-
entity_class.adaptor.count( attribute.to_s, find_options ) > 0
|
14
|
-
end
|
15
|
-
|
16
|
-
def populate_current( editor, model_index )
|
17
|
-
# already done in the SQL query in populate, so don't even check
|
18
|
-
end
|
19
|
-
|
20
|
-
def populate( editor, model_index )
|
21
|
-
# we only use the first column, so use the second
|
22
|
-
# column to sort by, since SQL requires the order by clause
|
23
|
-
# to be in the select list where distinct is involved
|
24
|
-
entity_class.adaptor.attribute_list( attribute, model_index.attribute_value, field.description, field.frequency, find_options ) do |row|
|
25
|
-
value = row[attribute]
|
26
|
-
editor.add_item( value, value.to_variant )
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
9
|
+
# This might be unnecessary.
|
30
10
|
def translate_from_editor_text( editor, text )
|
31
11
|
text
|
32
12
|
end
|
33
13
|
end
|
34
14
|
|
35
15
|
end
|
16
|
+
|
17
|
+
require 'clevic/delegates/distinct_delegate.rb'
|
data/lib/clevic/qt/extensions.rb
CHANGED
@@ -13,7 +13,13 @@ module Qt
|
|
13
13
|
def full_edit
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
|
+
class KeyEvent
|
18
|
+
def inspect
|
19
|
+
"<Qt::KeyEvent text=#{text} key=#{key}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
17
23
|
# This provides a bunch of methods to get easy access to the entity
|
18
24
|
# and it's values directly from the index without having to keep
|
19
25
|
# asking the model and jumping through other unncessary hoops
|
@@ -44,4 +50,5 @@ module Qt
|
|
44
50
|
class MessageBox
|
45
51
|
include Clevic::AcceptReject
|
46
52
|
end
|
53
|
+
|
47
54
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Qt
|
2
|
+
# Implement the methods needed for ComboBox to work with the
|
3
|
+
# various Clevic::Delegate classes.
|
4
|
+
class ComboBox
|
5
|
+
def no_insert=( bool )
|
6
|
+
self.insert_policy = Qt::ComboBox::NoInsert if bool
|
7
|
+
end
|
8
|
+
|
9
|
+
def <<( item )
|
10
|
+
text, data = item_to_editor( item )
|
11
|
+
add_item( text, data.to_variant )
|
12
|
+
end
|
13
|
+
|
14
|
+
def include?( item )
|
15
|
+
text, data = item_to_editor( item )
|
16
|
+
find_data( data.to_variant ) != -1
|
17
|
+
end
|
18
|
+
|
19
|
+
def selected_item=( item )
|
20
|
+
text, data = item_to_editor( item )
|
21
|
+
self.current_index = find_data( data.to_variant )
|
22
|
+
end
|
23
|
+
|
24
|
+
def selected_item
|
25
|
+
delegate.editor_to_item( item_data( self.current_index ).value )
|
26
|
+
end
|
27
|
+
|
28
|
+
# wrapper for the delegate method so we don't have
|
29
|
+
# to keep checking for nil values
|
30
|
+
def item_to_editor( item )
|
31
|
+
if item
|
32
|
+
delegate.item_to_editor( item )
|
33
|
+
else
|
34
|
+
['', nil ]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# wrapper for the delegate method so we don't have
|
39
|
+
# to keep checking for nil values
|
40
|
+
def editor_to_item( data )
|
41
|
+
if data
|
42
|
+
delegate.editor_to_item( data )
|
43
|
+
else
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Adding these to Qt::Widget as the superclass
|
50
|
+
# doesn't work for some reason.
|
51
|
+
class ComboBox
|
52
|
+
attr_accessor :delegate
|
53
|
+
end
|
54
|
+
|
55
|
+
class LineEdit
|
56
|
+
attr_accessor :delegate
|
57
|
+
end
|
58
|
+
end
|
@@ -9,79 +9,39 @@ module Clevic
|
|
9
9
|
# The ids of the model objects are stored in the item data
|
10
10
|
# and the item text is fetched from them using attribute_path.
|
11
11
|
class RelationalDelegate < ComboDelegate
|
12
|
-
def
|
13
|
-
|
14
|
-
unless find_options[:conditions].nil?
|
15
|
-
find_options[:conditions].gsub!( /true/, field.related_class.adaptor.quoted_true )
|
16
|
-
find_options[:conditions].gsub!( /false/, field.related_class.adaptor.quoted_false )
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def needs_combo?
|
21
|
-
field.related_class.adaptor.count( :conditions => find_options[:conditions] ) > 0
|
12
|
+
def item_to_editor( item )
|
13
|
+
[ field.transform_attribute( item ), item.pk.to_variant ]
|
22
14
|
end
|
23
15
|
|
24
|
-
def
|
25
|
-
|
16
|
+
def editor_to_item( data )
|
17
|
+
entity.related_class[ data ]
|
26
18
|
end
|
27
19
|
|
28
|
-
#
|
29
|
-
def
|
30
|
-
|
31
|
-
# and it makes sense. This is to make sure that if the list
|
32
|
-
# is filtered, we always have the current value if the filter
|
33
|
-
# excludes it
|
34
|
-
unless model_index.nil?
|
35
|
-
item = model_index.attribute_value
|
36
|
-
if item
|
37
|
-
item_index = editor.find_data( item.id.to_variant )
|
38
|
-
if item_index == -1
|
39
|
-
add_to_list( editor, model_index, item )
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def populate( editor, model_index )
|
46
|
-
# add set of all possible related entities
|
47
|
-
field.related_class.adaptor.find( :all, find_options ).each do |x|
|
48
|
-
add_to_list( editor, model_index, x )
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def add_to_list( editor, model_index, item )
|
53
|
-
editor.add_item( model_index.field.transform_attribute( item ), item.id.to_variant )
|
54
|
-
end
|
55
|
-
|
56
|
-
# send data to the editor
|
57
|
-
def setEditorData( editor, model_index )
|
58
|
-
if is_combo?( editor )
|
20
|
+
# called by Qt when it wants to give the delegate an index to edit
|
21
|
+
def setEditorData( editor_widget, model_index )
|
22
|
+
if is_combo?( editor_widget )
|
59
23
|
unless model_index.attribute_value.nil?
|
60
|
-
|
24
|
+
editor_widget.selected_item = model_index.attribute_value
|
61
25
|
end
|
62
|
-
|
26
|
+
editor_widget.line_edit.andand.select_all
|
63
27
|
end
|
64
28
|
end
|
65
29
|
|
66
|
-
#
|
67
|
-
def
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
# return an AR entity object
|
72
|
-
def translate_from_editor_text( editor, text )
|
73
|
-
item_index = editor.find_text( text )
|
30
|
+
# return an entity object, given a text selection
|
31
|
+
def translate_from_editor_text( editor_widget, text )
|
32
|
+
item_index = editor_widget.find_text( text )
|
74
33
|
|
75
|
-
# fetch record id from
|
76
|
-
item_data =
|
34
|
+
# fetch record id from editor_widget item_data
|
35
|
+
item_data = editor_widget.item_data( item_index )
|
77
36
|
if item_data.valid?
|
78
37
|
# get the entity it refers to, if there is one
|
79
|
-
#
|
80
|
-
|
81
|
-
field.related_class.adaptor.find( item_data.to_int )
|
38
|
+
# return nil if nil was passed or the entity wasn't found
|
39
|
+
field.related_class[ item_data.to_int ]
|
82
40
|
end
|
83
41
|
end
|
84
42
|
|
85
43
|
end
|
86
44
|
|
87
45
|
end
|
46
|
+
|
47
|
+
require 'clevic/delegates/relational_delegate.rb'
|
@@ -1,44 +1,14 @@
|
|
1
1
|
require 'clevic/qt/combo_delegate.rb'
|
2
|
+
require 'clevic/qt/simplest_delegate.rb'
|
2
3
|
|
3
4
|
module Clevic
|
4
5
|
|
5
6
|
# A Combo box which allows a set of values. May or may not
|
6
7
|
# be restricted to the set.
|
7
8
|
class SetDelegate < ComboDelegate
|
8
|
-
|
9
|
-
def initialize( field )
|
10
|
-
raise "RestrictedDelegate must have a :set in options" if field.set.nil?
|
11
|
-
super
|
12
|
-
end
|
13
|
-
|
14
|
-
def needs_combo?
|
15
|
-
true
|
16
|
-
end
|
17
|
-
|
18
|
-
def restricted?
|
19
|
-
field.restricted || false
|
20
|
-
end
|
21
|
-
|
22
|
-
def populate( editor, model_index )
|
23
|
-
field.set_for( model_index.entity ).each do |item|
|
24
|
-
if item.is_a?( Array )
|
25
|
-
# this is a hash-like set, so use key as db value
|
26
|
-
# and value as display value
|
27
|
-
editor.add_item( item.last, item.first.to_variant )
|
28
|
-
else
|
29
|
-
editor.add_item( item, item.to_variant )
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def createEditor( parent_widget, style_option_view_item, model_index )
|
35
|
-
editor = super
|
36
|
-
|
37
|
-
# the set is provided, so never insert things
|
38
|
-
editor.insert_policy = Qt::ComboBox::NoInsert
|
39
|
-
editor
|
40
|
-
end
|
41
|
-
|
9
|
+
include SimplestDelegate
|
42
10
|
end
|
43
11
|
|
44
12
|
end
|
13
|
+
|
14
|
+
require 'clevic/delegates/set_delegate'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Clevic
|
2
|
+
|
3
|
+
# These methods are common between SetDelegate and DistinctDelegate
|
4
|
+
module SimplestDelegate
|
5
|
+
def item_to_editor( item )
|
6
|
+
if item.is_a?( Array )
|
7
|
+
[ item.last, item.first ]
|
8
|
+
else
|
9
|
+
[ item, item ]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def editor_to_item( data )
|
15
|
+
data.value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'Qt4'
|
2
1
|
require 'date'
|
3
2
|
|
4
3
|
require 'andand'
|
@@ -86,7 +85,7 @@ class TableModel < Qt::AbstractTableModel
|
|
86
85
|
retval = item_boolean_flags
|
87
86
|
end
|
88
87
|
|
89
|
-
unless model_index.field.read_only? ||
|
88
|
+
unless model_index.field.read_only? || read_only?
|
90
89
|
retval |= qt_item_is_editable.to_i
|
91
90
|
end
|
92
91
|
retval
|
@@ -101,12 +100,8 @@ class TableModel < Qt::AbstractTableModel
|
|
101
100
|
when Qt::Horizontal
|
102
101
|
labels[section]
|
103
102
|
when Qt::Vertical
|
104
|
-
#
|
105
|
-
|
106
|
-
collection[section].id
|
107
|
-
else
|
108
|
-
section
|
109
|
-
end
|
103
|
+
# display record number. Object id is in tooltip.
|
104
|
+
section+1
|
110
105
|
end
|
111
106
|
|
112
107
|
when qt_text_alignment_role
|
@@ -128,8 +123,12 @@ class TableModel < Qt::AbstractTableModel
|
|
128
123
|
case
|
129
124
|
when !collection[section].errors.empty?
|
130
125
|
'Invalid data'
|
131
|
-
when collection[section].
|
126
|
+
when collection[section].modified?
|
132
127
|
'Unsaved changes'
|
128
|
+
else
|
129
|
+
if collection.cached_at?( section )
|
130
|
+
collection[section].pk.inspect
|
131
|
+
end
|
133
132
|
end
|
134
133
|
end
|
135
134
|
|
@@ -198,7 +197,7 @@ class TableModel < Qt::AbstractTableModel
|
|
198
197
|
|
199
198
|
when qt_foreground_role
|
200
199
|
index.field.foreground_for( index.entity ) ||
|
201
|
-
if index.field.read_only? ||
|
200
|
+
if index.field.read_only? || read_only?
|
202
201
|
Qt::Color.new( 'dimgray' )
|
203
202
|
end
|
204
203
|
|
@@ -271,6 +270,7 @@ class TableModel < Qt::AbstractTableModel
|
|
271
270
|
# user-defined role
|
272
271
|
# TODO this only works with single-dotted paths
|
273
272
|
when qt_paste_role
|
273
|
+
puts "WARNING Qt::PasteRole Deprecated"
|
274
274
|
if index.meta.type == :association
|
275
275
|
field = index.field
|
276
276
|
candidates = field.related_class.find( :all, :conditions => [ "#{field.attribute_path[1]} = ?", variant.value ] )
|
data/lib/clevic/qt/table_view.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'Qt4'
|
3
1
|
require 'fastercsv'
|
4
2
|
require 'qtext/action_builder.rb'
|
5
|
-
|
6
3
|
require 'clevic/model_builder.rb'
|
7
4
|
require 'clevic/filter_command.rb'
|
8
5
|
|
@@ -46,10 +43,12 @@ class TableView < Qt::TableView
|
|
46
43
|
self.sorting_enabled = false
|
47
44
|
|
48
45
|
# set fonts
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
46
|
+
# TODO leave this here, but commented so we can see how to do it
|
47
|
+
# properly later.
|
48
|
+
#~ Qt::Font.new( font.family, font.point_size * 5 / 6 ).tap do |fnt|
|
49
|
+
#~ self.font = fnt
|
50
|
+
#~ self.horizontal_header.font = fnt
|
51
|
+
#~ end
|
53
52
|
|
54
53
|
self.context_menu_policy = Qt::ActionsContextMenu
|
55
54
|
end
|
@@ -205,21 +204,6 @@ class TableView < Qt::TableView
|
|
205
204
|
error_message.show
|
206
205
|
end
|
207
206
|
|
208
|
-
# This is to allow entity model UI handlers to tell the view
|
209
|
-
# whence to move the cursor when the current editor closes
|
210
|
-
# (see closeEditor).
|
211
|
-
# TODO not used?
|
212
|
-
def override_next_index( model_index )
|
213
|
-
self.next_index = model_index
|
214
|
-
end
|
215
|
-
|
216
|
-
# Call set_current_index with next_index ( from override_next_index )
|
217
|
-
# or model_index, in that order. Set next_index to nil afterwards.
|
218
|
-
def set_current_unless_override( model_index )
|
219
|
-
set_current_index( @next_index || model_index )
|
220
|
-
self.next_index = nil
|
221
|
-
end
|
222
|
-
|
223
207
|
# work around situation where an ItemDelegate is open
|
224
208
|
# when the surrouding tab is changed, but the right events
|
225
209
|
# don't arrive.
|
@@ -269,7 +253,7 @@ class TableView < Qt::TableView
|
|
269
253
|
end
|
270
254
|
|
271
255
|
rescue Exception => e
|
272
|
-
raise RuntimeError, "#{model.entity_view.class.name}.#{model_index.field.id}: #{e.message}",
|
256
|
+
raise RuntimeError, "#{model.entity_view.class.name}.#{model_index.field.id}: #{e.message}", e.backtrace
|
273
257
|
end
|
274
258
|
|
275
259
|
attr_accessor :before_edit_index
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require 'clevic/qt/
|
1
|
+
require 'clevic/qt/delegate.rb'
|
2
2
|
|
3
3
|
module Clevic
|
4
4
|
|
5
|
-
class TextDelegate <
|
5
|
+
class TextDelegate < Delegate
|
6
6
|
|
7
7
|
# Doesn't do anything useful yet, but I'm leaving
|
8
8
|
# it here so I don't have to change other code.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
=begin
|
2
2
|
** Form generated from reading ui file 'browser.ui'
|
3
3
|
**
|
4
|
-
** Created: Mon Jan
|
4
|
+
** Created: Mon Jan 31 16:10:23 2011
|
5
5
|
** by: Qt User Interface Compiler version 4.5.1
|
6
6
|
**
|
7
7
|
** WARNING! All changes made in this file will be lost when recompiling ui file!
|