clevic 0.13.0.b3 → 0.13.0.b5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/History.txt +21 -0
  2. data/Manifest.txt +91 -85
  3. data/README.txt +33 -18
  4. data/Rakefile +2 -3
  5. data/TODO +8 -14
  6. data/bin/clevic +18 -20
  7. data/lib/clevic.rb +7 -1
  8. data/lib/clevic/action_builder.rb +4 -1
  9. data/lib/clevic/ar_methods.rb +72 -57
  10. data/lib/clevic/attribute_list.rb +4 -0
  11. data/lib/clevic/cache_table.rb +43 -69
  12. data/lib/clevic/dataset_roller.rb +22 -0
  13. data/lib/clevic/delegate.rb +11 -5
  14. data/lib/clevic/delegates/combo_delegate.rb +156 -0
  15. data/lib/clevic/delegates/distinct_delegate.rb +48 -0
  16. data/lib/clevic/delegates/relational_delegate.rb +59 -0
  17. data/lib/clevic/delegates/set_delegate.rb +31 -0
  18. data/lib/clevic/field.rb +39 -55
  19. data/lib/clevic/field_valuer.rb +23 -10
  20. data/lib/clevic/filter_command.rb +22 -36
  21. data/lib/clevic/framework.rb +37 -0
  22. data/lib/clevic/generic_format.rb +5 -1
  23. data/lib/clevic/many_field.rb +28 -3
  24. data/lib/clevic/model_builder.rb +27 -32
  25. data/lib/clevic/ordered_dataset.rb +45 -0
  26. data/lib/clevic/qt.rb +4 -1
  27. data/lib/clevic/qt/action_builder.rb +9 -1
  28. data/lib/clevic/qt/browser.rb +1 -1
  29. data/lib/clevic/qt/clipboard.rb +3 -3
  30. data/lib/clevic/qt/combo_delegate.rb +25 -89
  31. data/lib/clevic/qt/delegate.rb +25 -0
  32. data/lib/clevic/qt/distinct_delegate.rb +5 -23
  33. data/lib/clevic/qt/extensions.rb +8 -1
  34. data/lib/clevic/qt/qt_combo_box.rb +58 -0
  35. data/lib/clevic/qt/relational_delegate.rb +18 -58
  36. data/lib/clevic/qt/set_delegate.rb +4 -34
  37. data/lib/clevic/qt/simplest_delegate.rb +19 -0
  38. data/lib/clevic/qt/table_model.rb +10 -10
  39. data/lib/clevic/qt/table_view.rb +7 -23
  40. data/lib/clevic/qt/text_delegate.rb +2 -2
  41. data/lib/clevic/qt/ui/browser_ui.rb +1 -1
  42. data/lib/clevic/qt/ui/search_dialog_ui.rb +1 -1
  43. data/lib/clevic/rails_models_loaders.rb +13 -0
  44. data/lib/clevic/record.rb +2 -2
  45. data/lib/clevic/sampler.rb +85 -39
  46. data/lib/clevic/sequel_ar_adapter.rb +1 -28
  47. data/lib/clevic/sequel_clevic.rb +68 -0
  48. data/lib/clevic/sequel_meta.rb +1 -13
  49. data/lib/clevic/subclasses.rb +18 -0
  50. data/lib/clevic/swing.rb +2 -1
  51. data/lib/clevic/swing/action.rb +27 -3
  52. data/lib/clevic/swing/action_builder.rb +0 -2
  53. data/lib/clevic/swing/browser.rb +1 -10
  54. data/lib/clevic/swing/combo_delegate.rb +45 -133
  55. data/lib/clevic/swing/delegate.rb +2 -0
  56. data/lib/clevic/swing/distinct_delegate.rb +2 -14
  57. data/lib/clevic/swing/relational_delegate.rb +2 -20
  58. data/lib/clevic/swing/set_delegate.rb +13 -28
  59. data/lib/clevic/swing/table_view.rb +1 -1
  60. data/lib/clevic/table_model.rb +3 -4
  61. data/lib/clevic/table_searcher.rb +10 -31
  62. data/lib/clevic/table_view.rb +97 -43
  63. data/lib/clevic/ui/browser_ui.rb +133 -0
  64. data/lib/clevic/ui/search_dialog_ui.rb +106 -0
  65. data/lib/clevic/version.rb +2 -2
  66. data/models/accounts_models.rb +24 -21
  67. data/models/times_models.rb +34 -28
  68. data/models/times_psql_models.rb +9 -3
  69. data/models/times_sqlite_models.rb +24 -1
  70. data/sql/times_sqlite.sql +3 -3
  71. data/tasks/clevic.rake +2 -2
  72. data/test/test_cache_table.rb +9 -19
  73. data/test/test_table_searcher.rb +2 -5
  74. metadata +95 -91
  75. data/lib/clevic/order_attribute.rb +0 -63
  76. data/lib/clevic/qt/boolean_delegate.rb +0 -8
  77. data/lib/clevic/qt/delegates.rb +0 -1
  78. data/lib/clevic/qt/item_delegate.rb +0 -66
  79. data/lib/clevic/sql_dialects.rb +0 -33
  80. data/tasks/website.rake +0 -25
  81. data/test/test_order_attribute.rb +0 -62
  82. 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
- def needs_combo?
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'
@@ -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 initialize( field )
13
- super
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 empty_set_message
25
- "There must be records in #{field.related_class.name.humanize} for this field to be editable."
16
+ def editor_to_item( data )
17
+ entity.related_class[ data ]
26
18
  end
27
19
 
28
- # add the current item, unless it's already in the combo data
29
- def populate_current( editor, model_index )
30
- # always add the current selection, if it isn't already there
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
- editor.current_index = editor.find_data( model_index.attribute_value.id.to_variant )
24
+ editor_widget.selected_item = model_index.attribute_value
61
25
  end
62
- editor.line_edit.select_all
26
+ editor_widget.line_edit.andand.select_all
63
27
  end
64
28
  end
65
29
 
66
- # don't allow new values
67
- def restricted?
68
- true
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 editor item_data
76
- item_data = editor.item_data( item_index )
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
- # use find_by_id so that if it's not found, nil will
80
- # be returned
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
- # options must contain a :set => [ ... ] to specify the set of values.
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? || model_index.entity.andand.readonly? || 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
- # don't force a fetch from the db
105
- if collection.cached_at?( section )
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].changed?
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? || index.entity.andand.readonly? || 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 ] )
@@ -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
- Qt::Font.new( font.family, font.point_size * 5 / 6 ).tap do |fnt|
50
- self.font = fnt
51
- self.horizontal_header.font = fnt
52
- end
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}", caller(0)
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/item_delegate.rb'
1
+ require 'clevic/qt/delegate.rb'
2
2
 
3
3
  module Clevic
4
4
 
5
- class TextDelegate < ItemDelegate
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 24 21:13:34 2011
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!