clevic 0.6.0 → 0.7.0

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.
@@ -1,8 +1,8 @@
1
1
  =begin
2
2
  ** Form generated from reading ui file 'search_dialog.ui'
3
3
  **
4
- ** Created: Mon Jul 7 22:49:30 2008
5
- ** by: Qt User Interface Compiler version 4.3.2
4
+ ** Created: Wed Jul 23 11:45:29 2008
5
+ ** by: Qt User Interface Compiler version 4.3.3
6
6
  **
7
7
  ** WARNING! All changes made in this file will be lost when recompiling ui file!
8
8
  =end
@@ -20,58 +20,57 @@ class Ui_SearchDialog
20
20
  attr_reader :backwards
21
21
 
22
22
  def setupUi(searchDialog)
23
- searchDialog.setObjectName("searchDialog")
24
- searchDialog.setWindowModality(Qt::WindowModal)
25
- searchDialog.setWindowIcon(Qt::Icon.new("../../hilfer/bin/hilfer-icon.png"))
23
+ if searchDialog.objectName.nil?
24
+ searchDialog.objectName = "searchDialog"
25
+ end
26
+ searchDialog.windowModality = Qt::WindowModal
27
+ searchDialog.resize(307, 400)
28
+ icon = Qt::Icon.new("../../hilfer/bin/hilfer-icon.png")
29
+ searchDialog.windowIcon = icon
26
30
  @button_box = Qt::DialogButtonBox.new(searchDialog)
27
- @button_box.setObjectName("button_box")
28
- @button_box.setGeometry(Qt::Rect.new(30, 240, 261, 32))
29
- @button_box.setOrientation(Qt::Horizontal)
30
- @button_box.setStandardButtons(Qt::DialogButtonBox::Cancel|Qt::DialogButtonBox::NoButton|Qt::DialogButtonBox::Ok)
31
+ @button_box.objectName = "button_box"
32
+ @button_box.geometry = Qt::Rect.new(30, 240, 261, 32)
33
+ @button_box.orientation = Qt::Horizontal
34
+ @button_box.standardButtons = Qt::DialogButtonBox::Cancel|Qt::DialogButtonBox::NoButton|Qt::DialogButtonBox::Ok
31
35
  @selected_rows = Qt::CheckBox.new(searchDialog)
32
- @selected_rows.setObjectName("selected_rows")
33
- @selected_rows.setEnabled(false)
34
- @selected_rows.setGeometry(Qt::Rect.new(30, 280, 191, 21))
36
+ @selected_rows.objectName = "selected_rows"
37
+ @selected_rows.enabled = false
38
+ @selected_rows.geometry = Qt::Rect.new(30, 280, 191, 21)
35
39
  @selected_columns = Qt::CheckBox.new(searchDialog)
36
- @selected_columns.setObjectName("selected_columns")
37
- @selected_columns.setEnabled(false)
38
- @selected_columns.setGeometry(Qt::Rect.new(30, 310, 191, 21))
40
+ @selected_columns.objectName = "selected_columns"
41
+ @selected_columns.enabled = false
42
+ @selected_columns.geometry = Qt::Rect.new(30, 310, 191, 21)
39
43
  @search_label = Qt::Label.new(searchDialog)
40
- @search_label.setObjectName("search_label")
41
- @search_label.setGeometry(Qt::Rect.new(20, 10, 51, 21))
42
- @search_label.setTextFormat(Qt::PlainText)
44
+ @search_label.objectName = "search_label"
45
+ @search_label.geometry = Qt::Rect.new(20, 10, 51, 21)
46
+ @search_label.textFormat = Qt::PlainText
43
47
  @search_combo = Qt::ComboBox.new(searchDialog)
44
- @search_combo.setObjectName("search_combo")
45
- @search_combo.setGeometry(Qt::Rect.new(90, 10, 201, 25))
46
- @search_combo.setFocusPolicy(Qt::StrongFocus)
47
- @search_combo.setEditable(true)
48
+ @search_combo.objectName = "search_combo"
49
+ @search_combo.geometry = Qt::Rect.new(90, 10, 201, 25)
50
+ @search_combo.focusPolicy = Qt::StrongFocus
51
+ @search_combo.editable = true
48
52
  @from_start = Qt::CheckBox.new(searchDialog)
49
- @from_start.setObjectName("from_start")
50
- @from_start.setGeometry(Qt::Rect.new(90, 50, 191, 21))
53
+ @from_start.objectName = "from_start"
54
+ @from_start.geometry = Qt::Rect.new(90, 50, 191, 21)
51
55
  @regex = Qt::CheckBox.new(searchDialog)
52
- @regex.setObjectName("regex")
53
- @regex.setGeometry(Qt::Rect.new(90, 80, 191, 21))
56
+ @regex.objectName = "regex"
57
+ @regex.geometry = Qt::Rect.new(90, 80, 191, 21)
54
58
  @whole_words = Qt::CheckBox.new(searchDialog)
55
- @whole_words.setObjectName("whole_words")
56
- @whole_words.setGeometry(Qt::Rect.new(90, 110, 191, 21))
59
+ @whole_words.objectName = "whole_words"
60
+ @whole_words.geometry = Qt::Rect.new(90, 110, 191, 21)
57
61
  @forwards = Qt::RadioButton.new(searchDialog)
58
- @forwards.setObjectName("forwards")
59
- @forwards.setGeometry(Qt::Rect.new(90, 140, 171, 26))
60
- @forwards.setChecked(true)
62
+ @forwards.objectName = "forwards"
63
+ @forwards.geometry = Qt::Rect.new(90, 140, 171, 26)
64
+ @forwards.checked = true
61
65
  @backwards = Qt::RadioButton.new(searchDialog)
62
- @backwards.setObjectName("backwards")
63
- @backwards.setGeometry(Qt::Rect.new(90, 170, 176, 26))
64
- @search_label.setBuddy(@search_combo)
65
- Qt::Widget::setTabOrder(@search_combo, @selected_columns)
66
- Qt::Widget::setTabOrder(@selected_columns, @selected_rows)
67
- Qt::Widget::setTabOrder(@selected_rows, @button_box)
66
+ @backwards.objectName = "backwards"
67
+ @backwards.geometry = Qt::Rect.new(90, 170, 176, 26)
68
+ @search_label.buddy = @search_combo
69
+ Qt::Widget.setTabOrder(@search_combo, @selected_columns)
70
+ Qt::Widget.setTabOrder(@selected_columns, @selected_rows)
71
+ Qt::Widget.setTabOrder(@selected_rows, @button_box)
68
72
 
69
73
  retranslateUi(searchDialog)
70
-
71
- size = Qt::Size.new(307, 400)
72
- size = size.expandedTo(searchDialog.minimumSizeHint())
73
- searchDialog.resize(size)
74
-
75
74
  Qt::Object.connect(@button_box, SIGNAL('accepted()'), searchDialog, SLOT('accept()'))
76
75
  Qt::Object.connect(@button_box, SIGNAL('rejected()'), searchDialog, SLOT('reject()'))
77
76
 
@@ -83,15 +82,15 @@ class Ui_SearchDialog
83
82
  end
84
83
 
85
84
  def retranslateUi(searchDialog)
86
- searchDialog.setWindowTitle(Qt::Application.translate("SearchDialog", "Search", nil, Qt::Application::UnicodeUTF8))
87
- @selected_rows.setText(Qt::Application.translate("SearchDialog", "Selected Rows", nil, Qt::Application::UnicodeUTF8))
88
- @selected_columns.setText(Qt::Application.translate("SearchDialog", "Selected Columns", nil, Qt::Application::UnicodeUTF8))
89
- @search_label.setText(Qt::Application.translate("SearchDialog", "Search", nil, Qt::Application::UnicodeUTF8))
90
- @from_start.setText(Qt::Application.translate("SearchDialog", "From &Start", nil, Qt::Application::UnicodeUTF8))
91
- @regex.setText(Qt::Application.translate("SearchDialog", "&Regular Expression", nil, Qt::Application::UnicodeUTF8))
92
- @whole_words.setText(Qt::Application.translate("SearchDialog", "&Whole Words", nil, Qt::Application::UnicodeUTF8))
93
- @forwards.setText(Qt::Application.translate("SearchDialog", "&Forwards", nil, Qt::Application::UnicodeUTF8))
94
- @backwards.setText(Qt::Application.translate("SearchDialog", "&Backwards", nil, Qt::Application::UnicodeUTF8))
85
+ searchDialog.windowTitle = Qt::Application.translate("SearchDialog", "Search", nil, Qt::Application::UnicodeUTF8)
86
+ @selected_rows.text = Qt::Application.translate("SearchDialog", "Selected Rows", nil, Qt::Application::UnicodeUTF8)
87
+ @selected_columns.text = Qt::Application.translate("SearchDialog", "Selected Columns", nil, Qt::Application::UnicodeUTF8)
88
+ @search_label.text = Qt::Application.translate("SearchDialog", "Search", nil, Qt::Application::UnicodeUTF8)
89
+ @from_start.text = Qt::Application.translate("SearchDialog", "From &Start", nil, Qt::Application::UnicodeUTF8)
90
+ @regex.text = Qt::Application.translate("SearchDialog", "&Regular Expression", nil, Qt::Application::UnicodeUTF8)
91
+ @whole_words.text = Qt::Application.translate("SearchDialog", "&Whole Words", nil, Qt::Application::UnicodeUTF8)
92
+ @forwards.text = Qt::Application.translate("SearchDialog", "&Forwards", nil, Qt::Application::UnicodeUTF8)
93
+ @backwards.text = Qt::Application.translate("SearchDialog", "&Backwards", nil, Qt::Application::UnicodeUTF8)
95
94
  end # retranslateUi
96
95
 
97
96
  def retranslate_ui(searchDialog)
@@ -1,7 +1,7 @@
1
1
  module Clevic #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 6
4
+ MINOR = 7
5
5
  TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
@@ -2,13 +2,17 @@ require 'clevic.rb'
2
2
 
3
3
  # db connection
4
4
  Clevic::DbOptions.connect( $options ) do
5
- database( debug? ? :accounts_test : :accounts )
5
+ # use a different db for testing, so real data doesn't get broken.
6
+ if options[:database].nil? || options[:database].empty?
7
+ database( debug? ? :accounts_test : :accounts )
8
+ else
9
+ database options[:database]
10
+ end
6
11
  adapter :postgresql
7
- username 'panic'
12
+ username 'accounts'
8
13
  end
9
14
 
10
- class Entry < ActiveRecord::Base
11
- include ActiveRecord::Dirty
15
+ class Entry < Clevic::Record
12
16
  belongs_to :debit, :class_name => 'Account', :foreign_key => 'debit_id'
13
17
  belongs_to :credit, :class_name => 'Account', :foreign_key => 'credit_id'
14
18
 
@@ -16,9 +20,9 @@ class Entry < ActiveRecord::Base
16
20
  def self.ui( parent )
17
21
  Clevic::TableView.new( self, parent ).create_model do
18
22
  plain :date, :sample => '88-WWW-99'
19
- distinct :description, :conditions => "now() - date <= '1 year'", :sample => 'm' * 26, :frequency => true
20
- relational :debit, 'name', :class_name => 'Account', :conditions => 'active = true', :order => 'lower(name)', :sample => 'Leilani Member Loan'
21
- relational :credit, 'name', :class_name => 'Account', :conditions => 'active = true', :order => 'lower(name)', :sample => 'Leilani Member Loan'
23
+ distinct :description, :conditions => "now() - date <= '1 year'", :sample => 'm' * 26
24
+ relational :debit, :display => 'name', :conditions => 'active = true', :order => 'lower(name)', :sample => 'Leilani Member Loan'
25
+ relational :credit, :display => 'name', :conditions => 'active = true', :order => 'lower(name)', :sample => 'Leilani Member Loan'
22
26
  plain :amount, :sample => 999999.99
23
27
  distinct :category
24
28
  plain :cheque_number
@@ -73,8 +77,7 @@ class Entry < ActiveRecord::Base
73
77
  end
74
78
  end
75
79
 
76
- class Account < ActiveRecord::Base
77
- include ActiveRecord::Dirty
80
+ class Account < Clevic::Record
78
81
  has_many :debits, :class_name => 'Entry', :foreign_key => 'debit_id'
79
82
  has_many :credits, :class_name => 'Entry', :foreign_key => 'credit_id'
80
83
 
@@ -92,6 +95,3 @@ class Account < ActiveRecord::Base
92
95
  end
93
96
  end
94
97
  end
95
-
96
- # order of tab display
97
- $options[:models] = [ Entry, Account ]
@@ -0,0 +1,19 @@
1
+ require 'clevic.rb'
2
+
3
+ # db connection
4
+ Clevic::DbOptions.connect do
5
+ database 'accounts_test'
6
+ adapter :postgresql
7
+ username 'accounts'
8
+ end
9
+
10
+ # minimal definition to get combo boxes to show up
11
+ class Entry < Clevic::Record
12
+ belongs_to :debit, :class_name => 'Account', :foreign_key => 'debit_id'
13
+ belongs_to :credit, :class_name => 'Account', :foreign_key => 'credit_id'
14
+ end
15
+
16
+ # minimal definition to get sensible values in combo boxes
17
+ class Account < Clevic::Record
18
+ def to_s; name; end
19
+ end
@@ -0,0 +1,156 @@
1
+ require 'clevic.rb'
2
+
3
+ # db connection options
4
+ db = Clevic::DbOptions.connect( $options ) do
5
+ # use a different db for testing, so real data doesn't get broken.
6
+ database( debug? ? :times_test : :times )
7
+ adapter :postgresql
8
+ username 'times'
9
+ end
10
+
11
+ # model definitions
12
+ class Entry < Clevic::Record
13
+ belongs_to :invoice
14
+ belongs_to :activity
15
+ belongs_to :project
16
+
17
+ # define how fields are displayed
18
+ def self.ui( parent )
19
+ Clevic::TableView.new( self, parent ).create_model do
20
+ plain :date, :sample => '28-Dec-08'
21
+ relational :project, :display => 'project', :conditions => 'active = true', :order => 'lower(project)'
22
+ relational :invoice, :display => 'invoice_number', :conditions => "status = 'not sent'", :order => 'invoice_number'
23
+ plain :start
24
+ plain :end
25
+ plain :description, :sample => 'This is a long string designed to hold lots of data and description'
26
+ relational :activity, :display => 'activity', :order => 'lower(activity)', :sample => 'Troubleshooting', :conditions => 'active = true'
27
+ distinct :module, :tooltip => 'Module or sub-project'
28
+ plain :charge, :tooltip => 'Is this time billable?'
29
+ distinct :person, :tooltip => 'The person who did the work'
30
+
31
+ records :order => 'date, start, id'
32
+ end
33
+ end
34
+
35
+ # called when a key is pressed in this model's table view
36
+ def self.key_press_event( event, current_index, view )
37
+ case
38
+ # copy almost all of the previous line
39
+ when event.ctrl? && event.quote_dbl?
40
+ if current_index.row > 1
41
+ # fetch previous item
42
+ model = current_index.model
43
+ previous_item = model.collection[current_index.row - 1]
44
+
45
+ # copy the relevant fields
46
+ current_index.entity.start = previous_item.end
47
+ [:date, :project, :invoice, :activity, :module, :charge, :person].each do |attr|
48
+ current_index.entity.send( "#{attr.to_s}=", previous_item.send( attr ) )
49
+ end
50
+
51
+ # tell view to update
52
+ top_left_index = model.create_index( current_index.row, 0 )
53
+ bottom_right_index = model.create_index( current_index.row, current_index.column + view.builder.fields.size )
54
+ view.dataChanged( top_left_index, bottom_right_index )
55
+
56
+ # move to end time field
57
+ view.override_next_index( model.create_index( current_index.row, view.builder.index( :end ) ) )
58
+ end
59
+ # don't let anybody else handle the keypress
60
+ return true
61
+
62
+ when event.ctrl? && event.i?
63
+ invoice_from_project( current_index, view )
64
+ # don't let anybody else handle the keypress
65
+ return true
66
+ end
67
+ end
68
+
69
+ # called when data is changed in this model's table view
70
+ def self.data_changed( top_left, bottom_right, view )
71
+ invoice_from_project( top_left, view ) if ( top_left == bottom_right )
72
+ end
73
+
74
+ def self.invoice_from_project( current_index, view )
75
+ # auto-complete invoice number field from project
76
+ current_field = current_index.attribute
77
+ if current_field == :project && current_index.entity.project != nil
78
+ # most recent entry, ordered in reverse
79
+ invoice = current_index.entity.project.latest_invoice
80
+
81
+ unless invoice.nil?
82
+ # make a reference to the invoice
83
+ current_index.entity.invoice = invoice
84
+
85
+ # update view from top_left to bottom_right
86
+ model = current_index.model
87
+ changed_index = model.create_index( current_index.row, view.builder.index( :invoice ) )
88
+ view.dataChanged( changed_index, changed_index )
89
+
90
+ # move edit cursor to start time field
91
+ view.override_next_index( model.create_index( current_index.row, view.builder.index( :start ) ) )
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ class Invoice < Clevic::Record
98
+ has_many :entries
99
+
100
+ # define how fields are displayed
101
+ def self.ui( parent )
102
+ Clevic::TableView.new( self, parent ).create_model do
103
+ plain :date
104
+ distinct :client
105
+ plain :invoice_number
106
+ restricted :status, :set => ['not sent', 'sent', 'paid', 'debt', 'writeoff', 'internal']
107
+ restricted :billing, :set => %w{Hours Quote Internal}
108
+ plain :quote_date
109
+ plain :quote_amount
110
+ plain :description
111
+
112
+ records :order => 'invoice_number'
113
+ end
114
+ end
115
+ end
116
+
117
+ class Project < Clevic::Record
118
+ has_many :entries
119
+
120
+ def self.ui( parent )
121
+ Clevic::TableView.new( Project, parent ).create_model do
122
+ plain :project
123
+ plain :description
124
+ distinct :client
125
+ plain :rate
126
+ plain :active
127
+
128
+ records :order => 'project'
129
+ end
130
+ end
131
+
132
+ # Return the latest invoice for this project
133
+ # Not part of the UI.
134
+ def latest_invoice
135
+ Invoice.find(
136
+ :first,
137
+ :conditions => ["client = ? and status = 'not sent'", self.client],
138
+ :order => 'invoice_number desc'
139
+ )
140
+ end
141
+
142
+ end
143
+
144
+ class Activity < Clevic::Record
145
+ has_many :entries
146
+
147
+ # define how fields are displayed
148
+ def self.ui( parent )
149
+ Clevic::TableView.new( Activity, parent ).create_model do
150
+ plain :activity
151
+ plain :active
152
+
153
+ records :order => 'activity'
154
+ end
155
+ end
156
+ end
@@ -2,14 +2,12 @@ require 'clevic.rb'
2
2
 
3
3
  # db connection options
4
4
  Clevic::DbOptions.connect( $options ) do
5
- database( debug? ? :times_test : :times )
6
- adapter :postgresql
7
- username 'panic'
5
+ database :times
6
+ adapter :sqlite3
8
7
  end
9
8
 
10
9
  # model definitions
11
- class Entry < ActiveRecord::Base
12
- include ActiveRecord::Dirty
10
+ class Entry < Clevic::Record
13
11
  belongs_to :invoice
14
12
  belongs_to :activity
15
13
  belongs_to :project
@@ -18,12 +16,12 @@ class Entry < ActiveRecord::Base
18
16
  def self.ui( parent )
19
17
  Clevic::TableView.new( self, parent ).create_model do
20
18
  plain :date, :sample => '28-Dec-08'
21
- relational :project, 'project', :conditions => 'active = true', :order => 'lower(project)'
22
- relational :invoice, 'invoice_number', :conditions => "status = 'not sent'", :order => 'invoice_number'
19
+ relational :project, :display => 'project', :conditions => "active = true", :order => 'lower(project)'
20
+ relational :invoice, :display => 'invoice_number', :conditions => "status = 'not sent'", :order => 'invoice_number'
23
21
  plain :start
24
22
  plain :end
25
23
  plain :description, :sample => 'This is a long string designed to hold lots of data and description'
26
- relational :activity, 'activity', :order => 'lower(activity)', :sample => 'Troubleshooting', :conditions => 'active = true'
24
+ relational :activity, :display => 'activity', :order => 'lower(activity)', :sample => 'Troubleshooting', :conditions => 'active = #{connection.quoted_true}'
27
25
  distinct :module, :tooltip => 'Module or sub-project'
28
26
  plain :charge, :tooltip => 'Is this time billable?'
29
27
  distinct :person, :tooltip => 'The person who did the work'
@@ -94,8 +92,7 @@ class Entry < ActiveRecord::Base
94
92
  end
95
93
  end
96
94
 
97
- class Project < ActiveRecord::Base
98
- include ActiveRecord::Dirty
95
+ class Project < Clevic::Record
99
96
  has_many :entries
100
97
 
101
98
  def self.ui( parent )
@@ -122,8 +119,7 @@ class Project < ActiveRecord::Base
122
119
 
123
120
  end
124
121
 
125
- class Activity < ActiveRecord::Base
126
- include ActiveRecord::Dirty
122
+ class Activity < Clevic::Record
127
123
  has_many :entries
128
124
 
129
125
  # define how fields are displayed
@@ -137,15 +133,14 @@ class Activity < ActiveRecord::Base
137
133
  end
138
134
  end
139
135
 
140
- class Invoice < ActiveRecord::Base
141
- include ActiveRecord::Dirty
136
+ class Invoice < Clevic::Record
142
137
  has_many :entries
143
138
 
144
139
  # define how fields are displayed
145
140
  def self.ui( parent )
146
141
  Clevic::TableView.new( Invoice, parent ).create_model do
147
142
  plain :date
148
- distinct :client, :frequency => true
143
+ distinct :client
149
144
  plain :invoice_number
150
145
  restricted :status, :set => ['not sent', 'sent', 'paid', 'debt', 'writeoff', 'internal']
151
146
  restricted :billing, :set => %w{Hours Quote Internal}
@@ -157,6 +152,3 @@ class Invoice < ActiveRecord::Base
157
152
  end
158
153
  end
159
154
  end
160
-
161
- # tab widget order
162
- $options[:models] = [ Entry, Invoice, Project, Activity ]