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.
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!