openall_time_applet 0.0.14 → 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/conf/db_schema.rb +12 -0
- data/glade/win_main.glade +1 -0
- data/glade/win_sync_overview.glade +21 -39
- data/gui/win_main.rb +1 -11
- data/gui/win_sync_overview.rb +158 -32
- data/lib/openall_time_applet.rb +30 -18
- data/models/timelog.rb +5 -1
- data/models/timelog_logged_time.rb +9 -0
- data/openall_time_applet.gemspec +3 -5
- metadata +4 -6
- data/glade/win_timelog_edit.glade +0 -440
- data/gui/win_overview.rb +0 -5
- data/gui/win_timelog_edit.rb +0 -153
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.15
|
data/conf/db_schema.rb
CHANGED
@@ -35,6 +35,7 @@ Openall_time_applet::DB_SCHEMA = {
|
|
35
35
|
{"name" => "task_id", "type" => "int"},
|
36
36
|
{"name" => "timestamp", "type" => "datetime"},
|
37
37
|
{"name" => "time", "type" => "int"},
|
38
|
+
{"name" => "time_sync", "type" => "varchar"},
|
38
39
|
{"name" => "timetype", "type" => "enum", "maxlength" => "'normal','overtime150','overtime200'", "default" => "normal"},
|
39
40
|
{"name" => "time_transport", "type" => "int"},
|
40
41
|
{"name" => "transportlength", "type" => "int"},
|
@@ -50,6 +51,17 @@ Openall_time_applet::DB_SCHEMA = {
|
|
50
51
|
"task_id"
|
51
52
|
]
|
52
53
|
},
|
54
|
+
"Timelog_logged_time" => {
|
55
|
+
"columns" => [
|
56
|
+
{"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
|
57
|
+
{"name" => "timelog_id", "type" => "int"},
|
58
|
+
{"name" => "timestamp_start", "type" => "datetime"},
|
59
|
+
{"name" => "timestamp_end", "type" => "datetime"}
|
60
|
+
],
|
61
|
+
"indexes" => [
|
62
|
+
"timelog_id"
|
63
|
+
]
|
64
|
+
},
|
53
65
|
"Worktime" => {
|
54
66
|
"columns" => [
|
55
67
|
{"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
|
data/glade/win_main.glade
CHANGED
@@ -14,6 +14,7 @@
|
|
14
14
|
</object>
|
15
15
|
<object class="GtkWindow" id="window">
|
16
16
|
<property name="can_focus">False</property>
|
17
|
+
<property name="title" translatable="yes">OpenAll Time Applet</property>
|
17
18
|
<property name="window_position">center</property>
|
18
19
|
<property name="default_width">640</property>
|
19
20
|
<signal name="destroy" handler="on_window_destroy" swapped="no"/>
|
@@ -6,7 +6,9 @@
|
|
6
6
|
<property name="can_focus">False</property>
|
7
7
|
<property name="title" translatable="yes">Overview of sync</property>
|
8
8
|
<property name="window_position">center</property>
|
9
|
-
<property name="default_width">
|
9
|
+
<property name="default_width">850</property>
|
10
|
+
<property name="default_height">480</property>
|
11
|
+
<signal name="destroy" handler="on_window_destroy" swapped="no"/>
|
10
12
|
<child>
|
11
13
|
<object class="GtkVBox" id="vbox1">
|
12
14
|
<property name="visible">True</property>
|
@@ -28,44 +30,22 @@
|
|
28
30
|
<property name="can_focus">False</property>
|
29
31
|
<property name="spacing">3</property>
|
30
32
|
<child>
|
31
|
-
<object class="
|
33
|
+
<object class="GtkViewport" id="viewport1">
|
32
34
|
<property name="visible">True</property>
|
33
35
|
<property name="can_focus">False</property>
|
34
|
-
<property name="n_columns">3</property>
|
35
36
|
<child>
|
36
|
-
<object class="
|
37
|
+
<object class="GtkScrolledWindow" id="scrolledwindow1">
|
37
38
|
<property name="visible">True</property>
|
38
|
-
<property name="can_focus">
|
39
|
-
<property name="
|
40
|
-
<property name="
|
41
|
-
<
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
<property name="can_focus">False</property>
|
48
|
-
<property name="xalign">0</property>
|
49
|
-
<property name="label" translatable="yes"><b>Logged time</b></property>
|
50
|
-
<property name="use_markup">True</property>
|
51
|
-
</object>
|
52
|
-
<packing>
|
53
|
-
<property name="left_attach">1</property>
|
54
|
-
<property name="right_attach">2</property>
|
55
|
-
</packing>
|
56
|
-
</child>
|
57
|
-
<child>
|
58
|
-
<object class="GtkLabel" id="label5">
|
59
|
-
<property name="visible">True</property>
|
60
|
-
<property name="can_focus">False</property>
|
61
|
-
<property name="xalign">0</property>
|
62
|
-
<property name="label" translatable="yes"><b>Sync. as time</b></property>
|
63
|
-
<property name="use_markup">True</property>
|
39
|
+
<property name="can_focus">True</property>
|
40
|
+
<property name="hscrollbar_policy">automatic</property>
|
41
|
+
<property name="vscrollbar_policy">automatic</property>
|
42
|
+
<child>
|
43
|
+
<object class="GtkTreeView" id="tvTimelogs">
|
44
|
+
<property name="visible">True</property>
|
45
|
+
<property name="can_focus">True</property>
|
46
|
+
</object>
|
47
|
+
</child>
|
64
48
|
</object>
|
65
|
-
<packing>
|
66
|
-
<property name="left_attach">2</property>
|
67
|
-
<property name="right_attach">3</property>
|
68
|
-
</packing>
|
69
49
|
</child>
|
70
50
|
</object>
|
71
51
|
<packing>
|
@@ -98,7 +78,7 @@
|
|
98
78
|
</child>
|
99
79
|
</object>
|
100
80
|
<packing>
|
101
|
-
<property name="expand">
|
81
|
+
<property name="expand">False</property>
|
102
82
|
<property name="fill">True</property>
|
103
83
|
<property name="position">1</property>
|
104
84
|
</packing>
|
@@ -111,24 +91,26 @@
|
|
111
91
|
<object class="GtkLabel" id="label2">
|
112
92
|
<property name="visible">True</property>
|
113
93
|
<property name="can_focus">False</property>
|
114
|
-
<property name="label" translatable="yes"><b>
|
94
|
+
<property name="label" translatable="yes"><b>Prepare synchronization</b></property>
|
115
95
|
<property name="use_markup">True</property>
|
116
96
|
</object>
|
117
97
|
</child>
|
118
98
|
</object>
|
119
99
|
<packing>
|
120
|
-
<property name="expand">
|
100
|
+
<property name="expand">True</property>
|
121
101
|
<property name="fill">True</property>
|
122
102
|
<property name="position">0</property>
|
123
103
|
</packing>
|
124
104
|
</child>
|
125
105
|
<child>
|
126
|
-
<object class="GtkLabel" id="
|
106
|
+
<object class="GtkLabel" id="labTotal">
|
127
107
|
<property name="visible">True</property>
|
128
108
|
<property name="can_focus">False</property>
|
109
|
+
<property name="xalign">0</property>
|
110
|
+
<property name="label" translatable="yes">[totals]</property>
|
129
111
|
</object>
|
130
112
|
<packing>
|
131
|
-
<property name="expand">
|
113
|
+
<property name="expand">False</property>
|
132
114
|
<property name="fill">True</property>
|
133
115
|
<property name="position">1</property>
|
134
116
|
</packing>
|
data/gui/win_main.rb
CHANGED
@@ -128,16 +128,6 @@ class Openall_time_applet::Gui::Win_main
|
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
|
-
def on_tvTimelogs_row_activated(*args)
|
132
|
-
row = @gui["tvTimelogs"].sel
|
133
|
-
return nil if !row
|
134
|
-
|
135
|
-
timelog = @args[:oata].ob.get(:Timelog, row[0])
|
136
|
-
win_timelog_edit = @args[:oata].show_timelog_edit(timelog)
|
137
|
-
win_timelog_edit.gui["window"].modal = @gui["window"]
|
138
|
-
win_timelog_edit.gui["window"].transient_for = @gui["window"]
|
139
|
-
end
|
140
|
-
|
141
131
|
def on_imiQuit_activate
|
142
132
|
@gui["window"].destroy
|
143
133
|
end
|
@@ -180,7 +170,7 @@ class Openall_time_applet::Gui::Win_main
|
|
180
170
|
end
|
181
171
|
|
182
172
|
def on_btnSync_clicked
|
183
|
-
@args[:oata].sync_static do
|
173
|
+
@args[:oata].sync_static("transient_for" => @gui["window"]) do
|
184
174
|
@args[:oata].sync
|
185
175
|
end
|
186
176
|
end
|
data/gui/win_sync_overview.rb
CHANGED
@@ -6,30 +6,95 @@ class Openall_time_applet::Gui::Win_sync_overview
|
|
6
6
|
@gui = Gtk::Builder.new.add("../glade/win_sync_overview.glade")
|
7
7
|
@gui.translate
|
8
8
|
@gui.connect_signals{|h|method(h)}
|
9
|
-
@gui["btnSync"].label = _("
|
9
|
+
@gui["btnSync"].label = _("Transfer")
|
10
10
|
|
11
|
-
#
|
12
|
-
|
11
|
+
#Generate list-store containing tasks for the task-column.
|
12
|
+
task_ls = Gtk::ListStore.new(String, String)
|
13
|
+
iter = task_ls.append
|
14
|
+
iter[0] = _("None")
|
15
|
+
iter[1] = 0.to_s
|
13
16
|
|
17
|
+
tasks = [_("Choose:")]
|
18
|
+
@args[:oata].ob.list(:Task, {"orderby" => "title"}) do |task|
|
19
|
+
iter = task_ls.append
|
20
|
+
iter[0] = task[:title]
|
21
|
+
iter[1] = task.id.to_s
|
22
|
+
tasks << task
|
23
|
+
end
|
24
|
+
|
25
|
+
#Initialize timelog treeview.
|
26
|
+
init_data = Knj::Gtk2::Tv.init(@gui["tvTimelogs"], [
|
27
|
+
_("ID"),
|
28
|
+
_("Description"),
|
29
|
+
_("Timestamp"),
|
30
|
+
_("Time"),
|
31
|
+
_("Transport"),
|
32
|
+
_("Length"),
|
33
|
+
_("Transport descr."),
|
34
|
+
_("Transport costs"),
|
35
|
+
{
|
36
|
+
:title => _("Fixed travel"),
|
37
|
+
:type => :toggle
|
38
|
+
},
|
39
|
+
{
|
40
|
+
:title => _("Int. work"),
|
41
|
+
:type => :toggle
|
42
|
+
},
|
43
|
+
{
|
44
|
+
:title => _("Sync?"),
|
45
|
+
:type => :toggle
|
46
|
+
},
|
47
|
+
{
|
48
|
+
:title => _("Task"),
|
49
|
+
:type => :combo,
|
50
|
+
:model => task_ls,
|
51
|
+
:has_entry => false
|
52
|
+
},
|
53
|
+
_("Sync time")
|
54
|
+
])
|
55
|
+
|
56
|
+
#Make columns editable.
|
57
|
+
Knj::Gtk2::Tv.editable_text_renderers_to_model(
|
58
|
+
:ob => @args[:oata].ob,
|
59
|
+
:tv => @gui["tvTimelogs"],
|
60
|
+
:model_class => :Timelog,
|
61
|
+
:renderers => init_data[:renderers],
|
62
|
+
:change_before => proc{ @dont_reload = true },
|
63
|
+
:change_after => proc{ @dont_reload = false; self.update_totals },
|
64
|
+
:cols => {
|
65
|
+
1 => :descr,
|
66
|
+
2 => {:col => :timestamp, :type => :datetime},
|
67
|
+
3 => {:col => :time, :type => :time_as_sec},
|
68
|
+
4 => {:col => :time_transport, :type => :time_as_sec},
|
69
|
+
5 => {:col => :transportlength, :type => :int},
|
70
|
+
6 => {:col => :transportdescription},
|
71
|
+
7 => {:col => :transportcosts, :type => :human_number, :decimals => 2},
|
72
|
+
8 => {:col => :travelfixed},
|
73
|
+
9 => {:col => :workinternal},
|
74
|
+
10 => {:col => :sync_need},
|
75
|
+
11 => {
|
76
|
+
:col => :task_id,
|
77
|
+
:value_callback => lambda{ |data|
|
78
|
+
task = @args[:oata].ob.get_by(:Task, {"title" => data[:value]})
|
79
|
+
|
80
|
+
if !task
|
81
|
+
return 0
|
82
|
+
else
|
83
|
+
return task.id
|
84
|
+
end
|
85
|
+
},
|
86
|
+
:value_set_callback => proc{ |data| data[:model].task_name }
|
87
|
+
},
|
88
|
+
12 => {:col => :time_sync, :type => :time_as_sec}
|
89
|
+
}
|
90
|
+
)
|
91
|
+
@gui["tvTimelogs"].columns[0].visible = false
|
92
|
+
|
93
|
+
|
94
|
+
=begin
|
14
95
|
rowc = 1
|
15
96
|
@args[:oata].ob.list(:Timelog, {"sync_need" => 1, "task_id_not" => 0}) do |timelog|
|
16
|
-
#Read time and transport from timelog.
|
17
|
-
time = timelog[:time].to_i
|
18
|
-
transport = timelog[:time_transport].to_i
|
19
|
-
|
20
|
-
#If transport is logged, then the work if offsite. It should be rounded up by 30 min. Else 15 min. round up.
|
21
|
-
if transport > 0
|
22
|
-
roundup = 1800
|
23
|
-
else
|
24
|
-
roundup = 900
|
25
|
-
end
|
26
97
|
|
27
|
-
#Do the actual counting.
|
28
|
-
count_rounded_time = 0
|
29
|
-
loop do
|
30
|
-
break if count_rounded_time >= time
|
31
|
-
count_rounded_time += roundup
|
32
|
-
end
|
33
98
|
|
34
99
|
#Spawn widgets.
|
35
100
|
timelog_label = Gtk::Label.new(timelog[:descr])
|
@@ -42,6 +107,7 @@ class Openall_time_applet::Gui::Win_sync_overview
|
|
42
107
|
|
43
108
|
sync_time_text = Gtk::Entry.new
|
44
109
|
sync_time_text.text = Knj::Strings.secs_to_human_time_str(count_rounded_time)
|
110
|
+
sync_time_text.signal_connect(:changed, &self.method(:on_syncTimeText_changed))
|
45
111
|
@sync_time_text_widgets[timelog.id] = sync_time_text
|
46
112
|
|
47
113
|
#Attach widgets in table.
|
@@ -51,8 +117,14 @@ class Openall_time_applet::Gui::Win_sync_overview
|
|
51
117
|
|
52
118
|
rowc += 1
|
53
119
|
end
|
120
|
+
=end
|
54
121
|
|
55
|
-
|
122
|
+
self.reload_timelogs
|
123
|
+
self.update_totals
|
124
|
+
|
125
|
+
@reload_id = @args[:oata].ob.connect("object" => :Timelog, "signals" => ["add", "update", "delete"], &self.method(:reload_timelogs))
|
126
|
+
|
127
|
+
if @timelogs_count <= 0
|
56
128
|
#Show error-message and destroy the window, if no timelogs was to be synced.
|
57
129
|
Knj::Gtk2.msgbox("msg" => _("There is nothing to sync at this time."), "run" => false)
|
58
130
|
@gui["window"].destroy
|
@@ -62,20 +134,53 @@ class Openall_time_applet::Gui::Win_sync_overview
|
|
62
134
|
end
|
63
135
|
end
|
64
136
|
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
137
|
+
def reload_timelogs
|
138
|
+
return nil if @dont_reload or @gui["tvTimelogs"].destroyed?
|
139
|
+
@gui["tvTimelogs"].model.clear
|
140
|
+
@timelogs_count = 0
|
141
|
+
@args[:oata].ob.list(:Timelog, {"sync_need" => 1, "task_id_not" => 0, "orderby" => "timestamp"}) do |timelog|
|
142
|
+
#Read time and transport from timelog.
|
143
|
+
time = timelog[:time].to_i
|
144
|
+
transport = timelog[:time_transport].to_i
|
145
|
+
|
146
|
+
#If transport is logged, then the work if offsite. It should be rounded up by 30 min. Else 15 min. round up.
|
147
|
+
if transport > 0
|
148
|
+
roundup = 1800
|
149
|
+
else
|
150
|
+
roundup = 900
|
151
|
+
end
|
152
|
+
|
153
|
+
#Do the actual counting.
|
154
|
+
count_rounded_time = 0
|
155
|
+
loop do
|
156
|
+
break if count_rounded_time >= time
|
157
|
+
count_rounded_time += roundup
|
77
158
|
end
|
78
159
|
|
160
|
+
#Set sync-time on timelog.
|
161
|
+
timelog[:time_sync] = count_rounded_time
|
162
|
+
|
163
|
+
Knj::Gtk2::Tv.append(@gui["tvTimelogs"], [
|
164
|
+
timelog.id,
|
165
|
+
timelog[:descr],
|
166
|
+
timelog.timestamp_str,
|
167
|
+
timelog.time_as_human,
|
168
|
+
timelog.time_transport_as_human,
|
169
|
+
Knj::Locales.number_out(timelog[:transportlength], 0),
|
170
|
+
timelog.transport_descr_short,
|
171
|
+
Knj::Locales.number_out(timelog[:transportcosts], 2),
|
172
|
+
Knj::Strings.yn_str(timelog[:travelfixed], true, false),
|
173
|
+
Knj::Strings.yn_str(timelog[:workinternal], true, false),
|
174
|
+
Knj::Strings.yn_str(timelog[:sync_need], true, false),
|
175
|
+
timelog.task_name,
|
176
|
+
Knj::Strings.secs_to_human_time_str(count_rounded_time)
|
177
|
+
])
|
178
|
+
@timelogs_count += 1
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def on_btnSync_clicked
|
183
|
+
begin
|
79
184
|
#Destroy this window and start syncing for real.
|
80
185
|
@gui["window"].destroy
|
81
186
|
@args[:oata].sync_real
|
@@ -83,4 +188,25 @@ class Openall_time_applet::Gui::Win_sync_overview
|
|
83
188
|
Knj::Gtk2.msgbox(Knj::Errors.error_str(e))
|
84
189
|
end
|
85
190
|
end
|
191
|
+
|
192
|
+
def update_totals
|
193
|
+
total_secs = 0
|
194
|
+
|
195
|
+
@gui["tvTimelogs"].model.each do |model, path, iter|
|
196
|
+
time_val = @gui["tvTimelogs"].model.get_value(iter, 12)
|
197
|
+
|
198
|
+
begin
|
199
|
+
total_secs += Knj::Strings.human_time_str_to_secs(time_val)
|
200
|
+
rescue
|
201
|
+
#ignore - user is properly entering stuff.
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
@gui["labTotal"].markup = "<b>#{_("Total hours:")}</b> #{Knj::Strings.secs_to_human_time_str(total_secs)}"
|
206
|
+
end
|
207
|
+
|
208
|
+
def on_window_destroy
|
209
|
+
#Unconnect reload-event. Else it will crash on call to destroyed object. Also frees up various ressources.
|
210
|
+
@args[:oata].ob.unconnect("object" => :Timelog, "conn_id" => @reload_id)
|
211
|
+
end
|
86
212
|
end
|
data/lib/openall_time_applet.rb
CHANGED
@@ -239,18 +239,6 @@ class Openall_time_applet
|
|
239
239
|
end
|
240
240
|
end
|
241
241
|
|
242
|
-
def show_timelog_new
|
243
|
-
Knj::Gtk2::Window.unique!("timelog_new") do
|
244
|
-
Openall_time_applet::Gui::Win_timelog_edit.new(:oata => self)
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
def show_timelog_edit(timelog)
|
249
|
-
Knj::Gtk2::Window.unique!("timelog_edit_#{timelog.id}") do
|
250
|
-
Openall_time_applet::Gui::Win_timelog_edit.new(:oata => self, :timelog => timelog)
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
242
|
def show_overview
|
255
243
|
Knj::Gtk2::Window.unique!("overview") do
|
256
244
|
Openall_time_applet::Gui::Win_overview.new(:oata => self)
|
@@ -284,7 +272,7 @@ class Openall_time_applet
|
|
284
272
|
|
285
273
|
#Synchronizes organisations, tasks and worktimes.
|
286
274
|
def sync_static(args = nil)
|
287
|
-
sw = Knj::Gtk2::StatusWindow.new
|
275
|
+
sw = Knj::Gtk2::StatusWindow.new("transient_for" => args["transient_for"])
|
288
276
|
|
289
277
|
return Knj::Thread.new do
|
290
278
|
begin
|
@@ -301,11 +289,11 @@ class Openall_time_applet
|
|
301
289
|
sw.percent = 1
|
302
290
|
|
303
291
|
sleep 1 if !block_given?
|
304
|
-
sw.destroy
|
292
|
+
sw.destroy if sw
|
305
293
|
sw = nil
|
306
294
|
yield if block_given?
|
307
295
|
rescue => e
|
308
|
-
sw.destroy
|
296
|
+
sw.destroy if sw
|
309
297
|
sw = nil
|
310
298
|
Knj::Gtk2.msgbox("msg" => Knj::Errors.error_str(e), "type" => "warning", "title" => _("Error"), "run" => false)
|
311
299
|
ensure
|
@@ -353,6 +341,7 @@ class Openall_time_applet
|
|
353
341
|
:time => @timelog_active[:time].to_i + secs_passed,
|
354
342
|
:sync_need => 1
|
355
343
|
)
|
344
|
+
@timelog_logged_time[:timestamp_end] = Time.now
|
356
345
|
end
|
357
346
|
|
358
347
|
@timelog_active = nil
|
@@ -362,10 +351,33 @@ class Openall_time_applet
|
|
362
351
|
|
363
352
|
#Sets a new timelog to track. Stops tracking of previous timelog if already tracking.
|
364
353
|
def timelog_active=(timelog)
|
365
|
-
|
354
|
+
begin
|
355
|
+
#Check if there has been logged time another day - if so, clone it and begin logging on the clone instead.
|
356
|
+
tlt = @ob.list(:Timelog_logged_time, {
|
357
|
+
"timelog" => timelog,
|
358
|
+
"timestamp_start_day_not" => Time.now,
|
359
|
+
"limit" => 1
|
360
|
+
})
|
361
|
+
if !tlt.empty?
|
362
|
+
timelog = @ob.add(:Timelog, {
|
363
|
+
:task_id => timelog[:task_id],
|
364
|
+
:timestamp => Time.now,
|
365
|
+
:descr => timelog[:descr],
|
366
|
+
:transportdescription => timelog[:transportdescription],
|
367
|
+
:workinternal => timelog[:workinternal],
|
368
|
+
:timetype => timelog[:timetype]
|
369
|
+
})
|
370
|
+
#raise sprintf(_("You have already logged on this timelog on %s"), tlt.first.timestamp_start.out)
|
371
|
+
end
|
372
|
+
|
373
|
+
self.timelog_stop_tracking
|
374
|
+
@timelog_logged_time = @ob.add(:Timelog_logged_time, {:timelog_id => timelog.id})
|
375
|
+
@timelog_active = timelog
|
376
|
+
@timelog_active_time = Time.new
|
377
|
+
rescue => e
|
378
|
+
Knj::Gtk2.msgbox("msg" => Knj::Errors.error_str(e), "type" => "warning", "title" => _("Error"), "run" => false)
|
379
|
+
end
|
366
380
|
|
367
|
-
@timelog_active = timelog
|
368
|
-
@timelog_active_time = Time.new
|
369
381
|
@ti.update_icon if @ti
|
370
382
|
end
|
371
383
|
|
data/models/timelog.rb
CHANGED
@@ -3,6 +3,10 @@ class Openall_time_applet::Models::Timelog < Knj::Datarow
|
|
3
3
|
:Task
|
4
4
|
]
|
5
5
|
|
6
|
+
has_many [
|
7
|
+
{:class => :Timelog_logged_time, :col => :timelog_id, :method => :logged_times, :autodelete => true}
|
8
|
+
]
|
9
|
+
|
6
10
|
def initialize(*args, &block)
|
7
11
|
super(*args, &block)
|
8
12
|
|
@@ -22,7 +26,7 @@ class Openall_time_applet::Models::Timelog < Knj::Datarow
|
|
22
26
|
args[:oata].oa_conn do |conn|
|
23
27
|
#Go through timelogs that needs syncing and has a task set.
|
24
28
|
self.ob.list(:Timelog, {"sync_need" => 1, "task_id_not" => 0}) do |timelog|
|
25
|
-
secs_sum = timelog[:
|
29
|
+
secs_sum = timelog[:time_sync].to_i + timelog[:time_transport].to_i
|
26
30
|
next if secs_sum <= 0
|
27
31
|
|
28
32
|
#The timelog has not yet been created in OpenAll - create it!
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class Openall_time_applet::Models::Timelog_logged_time < Knj::Datarow
|
2
|
+
has_one [
|
3
|
+
{:class => :Timelog, :col => :timelog_id, :method => :timelog, :depends => true}
|
4
|
+
]
|
5
|
+
|
6
|
+
def self.add(d)
|
7
|
+
d.data[:timestamp_start] = Time.now if !d.data[:timestamp_start]
|
8
|
+
end
|
9
|
+
end
|
data/openall_time_applet.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{openall_time_applet}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.15"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Kasper Johansen"]
|
12
|
-
s.date = %q{2012-06-
|
12
|
+
s.date = %q{2012-06-25}
|
13
13
|
s.default_executable = %q{openall_time_applet.rb}
|
14
14
|
s.description = %q{Off-line time-tracking for OpenAll with syncing when online.}
|
15
15
|
s.email = %q{k@spernj.org}
|
@@ -40,14 +40,11 @@ Gem::Specification.new do |s|
|
|
40
40
|
"glade/win_overview.glade",
|
41
41
|
"glade/win_preferences.glade",
|
42
42
|
"glade/win_sync_overview.glade",
|
43
|
-
"glade/win_timelog_edit.glade",
|
44
43
|
"glade/win_worktime_overview.glade",
|
45
44
|
"gui/trayicon.rb",
|
46
45
|
"gui/win_main.rb",
|
47
|
-
"gui/win_overview.rb",
|
48
46
|
"gui/win_preferences.rb",
|
49
47
|
"gui/win_sync_overview.rb",
|
50
|
-
"gui/win_timelog_edit.rb",
|
51
48
|
"gui/win_worktime_overview.rb",
|
52
49
|
"lib/openall_time_applet.rb",
|
53
50
|
"locales/da_DK/LC_MESSAGES/default.mo",
|
@@ -55,6 +52,7 @@ Gem::Specification.new do |s|
|
|
55
52
|
"models/organisation.rb",
|
56
53
|
"models/task.rb",
|
57
54
|
"models/timelog.rb",
|
55
|
+
"models/timelog_logged_time.rb",
|
58
56
|
"models/worktime.rb",
|
59
57
|
"openall_time_applet.gemspec",
|
60
58
|
"spec/openall_time_applet_spec.rb",
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: openall_time_applet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.15
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Kasper Johansen
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-06-
|
13
|
+
date: 2012-06-25 00:00:00 +02:00
|
14
14
|
default_executable: openall_time_applet.rb
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -165,14 +165,11 @@ files:
|
|
165
165
|
- glade/win_overview.glade
|
166
166
|
- glade/win_preferences.glade
|
167
167
|
- glade/win_sync_overview.glade
|
168
|
-
- glade/win_timelog_edit.glade
|
169
168
|
- glade/win_worktime_overview.glade
|
170
169
|
- gui/trayicon.rb
|
171
170
|
- gui/win_main.rb
|
172
|
-
- gui/win_overview.rb
|
173
171
|
- gui/win_preferences.rb
|
174
172
|
- gui/win_sync_overview.rb
|
175
|
-
- gui/win_timelog_edit.rb
|
176
173
|
- gui/win_worktime_overview.rb
|
177
174
|
- lib/openall_time_applet.rb
|
178
175
|
- locales/da_DK/LC_MESSAGES/default.mo
|
@@ -180,6 +177,7 @@ files:
|
|
180
177
|
- models/organisation.rb
|
181
178
|
- models/task.rb
|
182
179
|
- models/timelog.rb
|
180
|
+
- models/timelog_logged_time.rb
|
183
181
|
- models/worktime.rb
|
184
182
|
- openall_time_applet.gemspec
|
185
183
|
- spec/openall_time_applet_spec.rb
|
@@ -198,7 +196,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
198
196
|
requirements:
|
199
197
|
- - ">="
|
200
198
|
- !ruby/object:Gem::Version
|
201
|
-
hash:
|
199
|
+
hash: 1181471258583995936
|
202
200
|
segments:
|
203
201
|
- 0
|
204
202
|
version: "0"
|
@@ -1,440 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<interface>
|
3
|
-
<requires lib="gtk+" version="2.24"/>
|
4
|
-
<!-- interface-naming-policy project-wide -->
|
5
|
-
<object class="GtkWindow" id="window">
|
6
|
-
<property name="can_focus">False</property>
|
7
|
-
<property name="title" translatable="yes">Timelog</property>
|
8
|
-
<property name="window_position">center</property>
|
9
|
-
<property name="default_width">360</property>
|
10
|
-
<child>
|
11
|
-
<object class="GtkVBox" id="vbox1">
|
12
|
-
<property name="visible">True</property>
|
13
|
-
<property name="can_focus">False</property>
|
14
|
-
<child>
|
15
|
-
<object class="GtkFrame" id="frame1">
|
16
|
-
<property name="visible">True</property>
|
17
|
-
<property name="can_focus">False</property>
|
18
|
-
<property name="label_xalign">0</property>
|
19
|
-
<property name="shadow_type">none</property>
|
20
|
-
<child>
|
21
|
-
<object class="GtkAlignment" id="alignment1">
|
22
|
-
<property name="visible">True</property>
|
23
|
-
<property name="can_focus">False</property>
|
24
|
-
<property name="left_padding">12</property>
|
25
|
-
<child>
|
26
|
-
<object class="GtkTable" id="table1">
|
27
|
-
<property name="visible">True</property>
|
28
|
-
<property name="can_focus">False</property>
|
29
|
-
<property name="n_rows">13</property>
|
30
|
-
<property name="n_columns">2</property>
|
31
|
-
<property name="column_spacing">3</property>
|
32
|
-
<property name="row_spacing">3</property>
|
33
|
-
<child>
|
34
|
-
<object class="GtkLabel" id="label3">
|
35
|
-
<property name="visible">True</property>
|
36
|
-
<property name="can_focus">False</property>
|
37
|
-
<property name="xalign">0</property>
|
38
|
-
<property name="label" translatable="yes">Description</property>
|
39
|
-
</object>
|
40
|
-
<packing>
|
41
|
-
<property name="x_options">GTK_FILL</property>
|
42
|
-
<property name="y_options">GTK_FILL</property>
|
43
|
-
</packing>
|
44
|
-
</child>
|
45
|
-
<child>
|
46
|
-
<object class="GtkLabel" id="label4">
|
47
|
-
<property name="visible">True</property>
|
48
|
-
<property name="can_focus">False</property>
|
49
|
-
<property name="xalign">0</property>
|
50
|
-
<property name="label" translatable="yes">Time</property>
|
51
|
-
</object>
|
52
|
-
<packing>
|
53
|
-
<property name="top_attach">1</property>
|
54
|
-
<property name="bottom_attach">2</property>
|
55
|
-
<property name="x_options">GTK_FILL</property>
|
56
|
-
<property name="y_options">GTK_FILL</property>
|
57
|
-
</packing>
|
58
|
-
</child>
|
59
|
-
<child>
|
60
|
-
<object class="GtkEntry" id="txtTime">
|
61
|
-
<property name="visible">True</property>
|
62
|
-
<property name="can_focus">True</property>
|
63
|
-
<property name="invisible_char">•</property>
|
64
|
-
<property name="primary_icon_activatable">False</property>
|
65
|
-
<property name="secondary_icon_activatable">False</property>
|
66
|
-
<property name="primary_icon_sensitive">True</property>
|
67
|
-
<property name="secondary_icon_sensitive">True</property>
|
68
|
-
</object>
|
69
|
-
<packing>
|
70
|
-
<property name="left_attach">1</property>
|
71
|
-
<property name="right_attach">2</property>
|
72
|
-
<property name="top_attach">1</property>
|
73
|
-
<property name="bottom_attach">2</property>
|
74
|
-
</packing>
|
75
|
-
</child>
|
76
|
-
<child>
|
77
|
-
<object class="GtkLabel" id="label5">
|
78
|
-
<property name="visible">True</property>
|
79
|
-
<property name="can_focus">False</property>
|
80
|
-
<property name="xalign">0</property>
|
81
|
-
<property name="label" translatable="yes">Transport</property>
|
82
|
-
</object>
|
83
|
-
<packing>
|
84
|
-
<property name="top_attach">2</property>
|
85
|
-
<property name="bottom_attach">3</property>
|
86
|
-
<property name="x_options">GTK_FILL</property>
|
87
|
-
<property name="y_options">GTK_FILL</property>
|
88
|
-
</packing>
|
89
|
-
</child>
|
90
|
-
<child>
|
91
|
-
<object class="GtkEntry" id="txtTimeTransport">
|
92
|
-
<property name="visible">True</property>
|
93
|
-
<property name="can_focus">True</property>
|
94
|
-
<property name="invisible_char">•</property>
|
95
|
-
<property name="primary_icon_activatable">False</property>
|
96
|
-
<property name="secondary_icon_activatable">False</property>
|
97
|
-
<property name="primary_icon_sensitive">True</property>
|
98
|
-
<property name="secondary_icon_sensitive">True</property>
|
99
|
-
</object>
|
100
|
-
<packing>
|
101
|
-
<property name="left_attach">1</property>
|
102
|
-
<property name="right_attach">2</property>
|
103
|
-
<property name="top_attach">2</property>
|
104
|
-
<property name="bottom_attach">3</property>
|
105
|
-
</packing>
|
106
|
-
</child>
|
107
|
-
<child>
|
108
|
-
<object class="GtkLabel" id="label6">
|
109
|
-
<property name="visible">True</property>
|
110
|
-
<property name="can_focus">False</property>
|
111
|
-
<property name="xalign">0</property>
|
112
|
-
<property name="label" translatable="yes">Task</property>
|
113
|
-
</object>
|
114
|
-
<packing>
|
115
|
-
<property name="top_attach">10</property>
|
116
|
-
<property name="bottom_attach">11</property>
|
117
|
-
<property name="x_options">GTK_FILL</property>
|
118
|
-
<property name="y_options">GTK_FILL</property>
|
119
|
-
</packing>
|
120
|
-
</child>
|
121
|
-
<child>
|
122
|
-
<object class="GtkComboBox" id="cbTask">
|
123
|
-
<property name="visible">True</property>
|
124
|
-
<property name="can_focus">False</property>
|
125
|
-
</object>
|
126
|
-
<packing>
|
127
|
-
<property name="left_attach">1</property>
|
128
|
-
<property name="right_attach">2</property>
|
129
|
-
<property name="top_attach">10</property>
|
130
|
-
<property name="bottom_attach">11</property>
|
131
|
-
</packing>
|
132
|
-
</child>
|
133
|
-
<child>
|
134
|
-
<object class="GtkCheckButton" id="cbShouldSync">
|
135
|
-
<property name="label" translatable="yes">Should sync</property>
|
136
|
-
<property name="visible">True</property>
|
137
|
-
<property name="can_focus">True</property>
|
138
|
-
<property name="receives_default">False</property>
|
139
|
-
<property name="use_action_appearance">False</property>
|
140
|
-
<property name="draw_indicator">True</property>
|
141
|
-
</object>
|
142
|
-
<packing>
|
143
|
-
<property name="right_attach">2</property>
|
144
|
-
<property name="top_attach">11</property>
|
145
|
-
<property name="bottom_attach">12</property>
|
146
|
-
<property name="x_options">GTK_FILL</property>
|
147
|
-
<property name="y_options">GTK_FILL</property>
|
148
|
-
</packing>
|
149
|
-
</child>
|
150
|
-
<child>
|
151
|
-
<object class="GtkCheckButton" id="cbStartTracking">
|
152
|
-
<property name="label" translatable="yes">Start tracking after saving</property>
|
153
|
-
<property name="visible">True</property>
|
154
|
-
<property name="can_focus">True</property>
|
155
|
-
<property name="receives_default">False</property>
|
156
|
-
<property name="use_action_appearance">False</property>
|
157
|
-
<property name="draw_indicator">True</property>
|
158
|
-
</object>
|
159
|
-
<packing>
|
160
|
-
<property name="right_attach">2</property>
|
161
|
-
<property name="top_attach">12</property>
|
162
|
-
<property name="bottom_attach">13</property>
|
163
|
-
</packing>
|
164
|
-
</child>
|
165
|
-
<child>
|
166
|
-
<object class="GtkEntry" id="txtDescr">
|
167
|
-
<property name="visible">True</property>
|
168
|
-
<property name="can_focus">True</property>
|
169
|
-
<property name="invisible_char">•</property>
|
170
|
-
<property name="primary_icon_activatable">False</property>
|
171
|
-
<property name="secondary_icon_activatable">False</property>
|
172
|
-
<property name="primary_icon_sensitive">True</property>
|
173
|
-
<property name="secondary_icon_sensitive">True</property>
|
174
|
-
</object>
|
175
|
-
<packing>
|
176
|
-
<property name="left_attach">1</property>
|
177
|
-
<property name="right_attach">2</property>
|
178
|
-
</packing>
|
179
|
-
</child>
|
180
|
-
<child>
|
181
|
-
<object class="GtkLabel" id="label7">
|
182
|
-
<property name="visible">True</property>
|
183
|
-
<property name="can_focus">False</property>
|
184
|
-
<property name="xalign">0</property>
|
185
|
-
<property name="label" translatable="yes">Transport length</property>
|
186
|
-
</object>
|
187
|
-
<packing>
|
188
|
-
<property name="top_attach">3</property>
|
189
|
-
<property name="bottom_attach">4</property>
|
190
|
-
<property name="x_options">GTK_FILL</property>
|
191
|
-
<property name="y_options">GTK_FILL</property>
|
192
|
-
</packing>
|
193
|
-
</child>
|
194
|
-
<child>
|
195
|
-
<object class="GtkLabel" id="label8">
|
196
|
-
<property name="visible">True</property>
|
197
|
-
<property name="can_focus">False</property>
|
198
|
-
<property name="xalign">0</property>
|
199
|
-
<property name="label" translatable="yes">Transport costs</property>
|
200
|
-
</object>
|
201
|
-
<packing>
|
202
|
-
<property name="top_attach">4</property>
|
203
|
-
<property name="bottom_attach">5</property>
|
204
|
-
<property name="x_options">GTK_FILL</property>
|
205
|
-
<property name="y_options">GTK_FILL</property>
|
206
|
-
</packing>
|
207
|
-
</child>
|
208
|
-
<child>
|
209
|
-
<object class="GtkEntry" id="txtTransportLength">
|
210
|
-
<property name="visible">True</property>
|
211
|
-
<property name="can_focus">True</property>
|
212
|
-
<property name="invisible_char">•</property>
|
213
|
-
<property name="primary_icon_activatable">False</property>
|
214
|
-
<property name="secondary_icon_activatable">False</property>
|
215
|
-
<property name="primary_icon_sensitive">True</property>
|
216
|
-
<property name="secondary_icon_sensitive">True</property>
|
217
|
-
</object>
|
218
|
-
<packing>
|
219
|
-
<property name="left_attach">1</property>
|
220
|
-
<property name="right_attach">2</property>
|
221
|
-
<property name="top_attach">3</property>
|
222
|
-
<property name="bottom_attach">4</property>
|
223
|
-
</packing>
|
224
|
-
</child>
|
225
|
-
<child>
|
226
|
-
<object class="GtkEntry" id="txtTransportCosts">
|
227
|
-
<property name="visible">True</property>
|
228
|
-
<property name="can_focus">True</property>
|
229
|
-
<property name="invisible_char">•</property>
|
230
|
-
<property name="primary_icon_activatable">False</property>
|
231
|
-
<property name="secondary_icon_activatable">False</property>
|
232
|
-
<property name="primary_icon_sensitive">True</property>
|
233
|
-
<property name="secondary_icon_sensitive">True</property>
|
234
|
-
</object>
|
235
|
-
<packing>
|
236
|
-
<property name="left_attach">1</property>
|
237
|
-
<property name="right_attach">2</property>
|
238
|
-
<property name="top_attach">4</property>
|
239
|
-
<property name="bottom_attach">5</property>
|
240
|
-
</packing>
|
241
|
-
</child>
|
242
|
-
<child>
|
243
|
-
<object class="GtkLabel" id="label9">
|
244
|
-
<property name="visible">True</property>
|
245
|
-
<property name="can_focus">False</property>
|
246
|
-
<property name="xalign">0</property>
|
247
|
-
<property name="label" translatable="yes">Transport description</property>
|
248
|
-
</object>
|
249
|
-
<packing>
|
250
|
-
<property name="top_attach">5</property>
|
251
|
-
<property name="bottom_attach">6</property>
|
252
|
-
<property name="x_options">GTK_FILL</property>
|
253
|
-
<property name="y_options">GTK_FILL</property>
|
254
|
-
</packing>
|
255
|
-
</child>
|
256
|
-
<child>
|
257
|
-
<object class="GtkEntry" id="txtTransportDescr">
|
258
|
-
<property name="visible">True</property>
|
259
|
-
<property name="can_focus">True</property>
|
260
|
-
<property name="invisible_char">•</property>
|
261
|
-
<property name="primary_icon_activatable">False</property>
|
262
|
-
<property name="secondary_icon_activatable">False</property>
|
263
|
-
<property name="primary_icon_sensitive">True</property>
|
264
|
-
<property name="secondary_icon_sensitive">True</property>
|
265
|
-
</object>
|
266
|
-
<packing>
|
267
|
-
<property name="left_attach">1</property>
|
268
|
-
<property name="right_attach">2</property>
|
269
|
-
<property name="top_attach">5</property>
|
270
|
-
<property name="bottom_attach">6</property>
|
271
|
-
</packing>
|
272
|
-
</child>
|
273
|
-
<child>
|
274
|
-
<object class="GtkCheckButton" id="cbWorkInternal">
|
275
|
-
<property name="label" translatable="yes">Internal work</property>
|
276
|
-
<property name="visible">True</property>
|
277
|
-
<property name="can_focus">True</property>
|
278
|
-
<property name="receives_default">False</property>
|
279
|
-
<property name="use_action_appearance">False</property>
|
280
|
-
<property name="draw_indicator">True</property>
|
281
|
-
</object>
|
282
|
-
<packing>
|
283
|
-
<property name="right_attach">2</property>
|
284
|
-
<property name="top_attach">6</property>
|
285
|
-
<property name="bottom_attach">7</property>
|
286
|
-
</packing>
|
287
|
-
</child>
|
288
|
-
<child>
|
289
|
-
<object class="GtkCheckButton" id="cbTravelFixed">
|
290
|
-
<property name="label" translatable="yes">Fixed travel</property>
|
291
|
-
<property name="visible">True</property>
|
292
|
-
<property name="can_focus">True</property>
|
293
|
-
<property name="receives_default">False</property>
|
294
|
-
<property name="use_action_appearance">False</property>
|
295
|
-
<property name="draw_indicator">True</property>
|
296
|
-
</object>
|
297
|
-
<packing>
|
298
|
-
<property name="right_attach">2</property>
|
299
|
-
<property name="top_attach">7</property>
|
300
|
-
<property name="bottom_attach">8</property>
|
301
|
-
<property name="x_options">GTK_FILL</property>
|
302
|
-
<property name="y_options">GTK_FILL</property>
|
303
|
-
</packing>
|
304
|
-
</child>
|
305
|
-
<child>
|
306
|
-
<object class="GtkLabel" id="label10">
|
307
|
-
<property name="visible">True</property>
|
308
|
-
<property name="can_focus">False</property>
|
309
|
-
<property name="xalign">0</property>
|
310
|
-
<property name="label" translatable="yes">Time type</property>
|
311
|
-
</object>
|
312
|
-
<packing>
|
313
|
-
<property name="top_attach">8</property>
|
314
|
-
<property name="bottom_attach">9</property>
|
315
|
-
<property name="x_options">GTK_FILL</property>
|
316
|
-
<property name="y_options">GTK_FILL</property>
|
317
|
-
</packing>
|
318
|
-
</child>
|
319
|
-
<child>
|
320
|
-
<object class="GtkComboBox" id="cbTimeType">
|
321
|
-
<property name="visible">True</property>
|
322
|
-
<property name="can_focus">False</property>
|
323
|
-
</object>
|
324
|
-
<packing>
|
325
|
-
<property name="left_attach">1</property>
|
326
|
-
<property name="right_attach">2</property>
|
327
|
-
<property name="top_attach">8</property>
|
328
|
-
<property name="bottom_attach">9</property>
|
329
|
-
</packing>
|
330
|
-
</child>
|
331
|
-
<child>
|
332
|
-
<object class="GtkLabel" id="label11">
|
333
|
-
<property name="visible">True</property>
|
334
|
-
<property name="can_focus">False</property>
|
335
|
-
<property name="xalign">0</property>
|
336
|
-
<property name="label" translatable="yes">Timestamp</property>
|
337
|
-
</object>
|
338
|
-
<packing>
|
339
|
-
<property name="top_attach">9</property>
|
340
|
-
<property name="bottom_attach">10</property>
|
341
|
-
<property name="x_options">GTK_FILL</property>
|
342
|
-
<property name="y_options">GTK_FILL</property>
|
343
|
-
</packing>
|
344
|
-
</child>
|
345
|
-
<child>
|
346
|
-
<object class="GtkEntry" id="txtTimestamp">
|
347
|
-
<property name="visible">True</property>
|
348
|
-
<property name="can_focus">True</property>
|
349
|
-
<property name="invisible_char">•</property>
|
350
|
-
<property name="primary_icon_activatable">False</property>
|
351
|
-
<property name="secondary_icon_activatable">False</property>
|
352
|
-
<property name="primary_icon_sensitive">True</property>
|
353
|
-
<property name="secondary_icon_sensitive">True</property>
|
354
|
-
</object>
|
355
|
-
<packing>
|
356
|
-
<property name="left_attach">1</property>
|
357
|
-
<property name="right_attach">2</property>
|
358
|
-
<property name="top_attach">9</property>
|
359
|
-
<property name="bottom_attach">10</property>
|
360
|
-
</packing>
|
361
|
-
</child>
|
362
|
-
</object>
|
363
|
-
</child>
|
364
|
-
</object>
|
365
|
-
</child>
|
366
|
-
<child type="label">
|
367
|
-
<object class="GtkLabel" id="label1">
|
368
|
-
<property name="visible">True</property>
|
369
|
-
<property name="can_focus">False</property>
|
370
|
-
<property name="label" translatable="yes"><b>Timelog</b></property>
|
371
|
-
<property name="use_markup">True</property>
|
372
|
-
</object>
|
373
|
-
</child>
|
374
|
-
</object>
|
375
|
-
<packing>
|
376
|
-
<property name="expand">False</property>
|
377
|
-
<property name="fill">True</property>
|
378
|
-
<property name="position">0</property>
|
379
|
-
</packing>
|
380
|
-
</child>
|
381
|
-
<child>
|
382
|
-
<object class="GtkHButtonBox" id="hbuttonbox1">
|
383
|
-
<property name="visible">True</property>
|
384
|
-
<property name="can_focus">False</property>
|
385
|
-
<property name="spacing">3</property>
|
386
|
-
<property name="layout_style">end</property>
|
387
|
-
<child>
|
388
|
-
<object class="GtkButton" id="btnRemove">
|
389
|
-
<property name="label">gtk-remove</property>
|
390
|
-
<property name="visible">True</property>
|
391
|
-
<property name="can_focus">True</property>
|
392
|
-
<property name="receives_default">True</property>
|
393
|
-
<property name="use_action_appearance">False</property>
|
394
|
-
<property name="use_stock">True</property>
|
395
|
-
<signal name="clicked" handler="on_btnRemove_clicked" swapped="no"/>
|
396
|
-
</object>
|
397
|
-
<packing>
|
398
|
-
<property name="expand">False</property>
|
399
|
-
<property name="fill">False</property>
|
400
|
-
<property name="position">0</property>
|
401
|
-
</packing>
|
402
|
-
</child>
|
403
|
-
<child>
|
404
|
-
<object class="GtkButton" id="btnSave">
|
405
|
-
<property name="label">gtk-save</property>
|
406
|
-
<property name="visible">True</property>
|
407
|
-
<property name="can_focus">True</property>
|
408
|
-
<property name="receives_default">True</property>
|
409
|
-
<property name="use_action_appearance">False</property>
|
410
|
-
<property name="use_stock">True</property>
|
411
|
-
<signal name="clicked" handler="on_btnSave_clicked" swapped="no"/>
|
412
|
-
</object>
|
413
|
-
<packing>
|
414
|
-
<property name="expand">False</property>
|
415
|
-
<property name="fill">False</property>
|
416
|
-
<property name="position">1</property>
|
417
|
-
</packing>
|
418
|
-
</child>
|
419
|
-
</object>
|
420
|
-
<packing>
|
421
|
-
<property name="expand">False</property>
|
422
|
-
<property name="fill">True</property>
|
423
|
-
<property name="position">1</property>
|
424
|
-
</packing>
|
425
|
-
</child>
|
426
|
-
<child>
|
427
|
-
<object class="GtkLabel" id="label2">
|
428
|
-
<property name="visible">True</property>
|
429
|
-
<property name="can_focus">False</property>
|
430
|
-
</object>
|
431
|
-
<packing>
|
432
|
-
<property name="expand">True</property>
|
433
|
-
<property name="fill">True</property>
|
434
|
-
<property name="position">2</property>
|
435
|
-
</packing>
|
436
|
-
</child>
|
437
|
-
</object>
|
438
|
-
</child>
|
439
|
-
</object>
|
440
|
-
</interface>
|
data/gui/win_overview.rb
DELETED
data/gui/win_timelog_edit.rb
DELETED
@@ -1,153 +0,0 @@
|
|
1
|
-
class Openall_time_applet::Gui::Win_timelog_edit
|
2
|
-
attr_reader :args, :gui
|
3
|
-
|
4
|
-
def initialize(args)
|
5
|
-
@args = args
|
6
|
-
|
7
|
-
@gui = Gtk::Builder.new.add("../glade/win_timelog_edit.glade")
|
8
|
-
@gui.translate
|
9
|
-
@gui.connect_signals{|h| method(h)}
|
10
|
-
|
11
|
-
tasks_opts = [_("None")] + @args[:oata].ob.list(:Task, {"orderby" => "openall_uid"})
|
12
|
-
@gui["cbTask"].init(tasks_opts)
|
13
|
-
|
14
|
-
Knj::Gtk2::Cb.init(
|
15
|
-
"cb" => @gui["cbTimeType"],
|
16
|
-
"items" => {
|
17
|
-
"normal" => _("Normal"),
|
18
|
-
"overtime150" => sprintf(_("Overtime %s"), 150),
|
19
|
-
"overtime200" => sprintf(_("Overtime %s"), 200)
|
20
|
-
}
|
21
|
-
)
|
22
|
-
|
23
|
-
|
24
|
-
#Set up completion for description entry.
|
25
|
-
ec = Gtk::EntryCompletion.new
|
26
|
-
ec.model = Gtk::ListStore.new(String)
|
27
|
-
ec.text_column = 0
|
28
|
-
@gui["txtDescr"].completion = ec
|
29
|
-
|
30
|
-
added = {}
|
31
|
-
@args[:oata].ob.list(:Worktime, {"orderby" => "timestamp"}) do |worktime|
|
32
|
-
next if added.key?(worktime[:comment])
|
33
|
-
added[worktime[:comment]] = true
|
34
|
-
ec.model.append[0] = worktime[:comment]
|
35
|
-
end
|
36
|
-
|
37
|
-
@args[:oata].ob.list(:Timelog, {"orderby" => "descr"}) do |timelog|
|
38
|
-
next if added.key?(timelog[:descr])
|
39
|
-
added[timelog[:descr]] = true
|
40
|
-
ec.model.append[0] = timelog[:descr]
|
41
|
-
end
|
42
|
-
|
43
|
-
ec.signal_connect("match-selected") do |me, model, iter|
|
44
|
-
text = model.get_value(iter, 0)
|
45
|
-
me.entry.text = text
|
46
|
-
true
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
|
-
#We are editting a timelog - set widget-values.
|
51
|
-
@timelog = @args[:timelog]
|
52
|
-
|
53
|
-
if @timelog
|
54
|
-
@gui["txtDescr"].text = @timelog[:descr]
|
55
|
-
@gui["txtTime"].text = @timelog.time_as_human
|
56
|
-
@gui["txtTimeTransport"].text = @timelog.time_transport_as_human
|
57
|
-
@gui["txtTransportLength"].text = Knj::Locales.number_out(@timelog[:transportlength], 0)
|
58
|
-
@gui["txtTransportCosts"].text = Knj::Locales.number_out(@timelog[:transportcosts], 0)
|
59
|
-
@gui["txtTransportDescr"].text = @timelog[:transportdescription]
|
60
|
-
@gui["cbTask"].sel = @timelog.task if @timelog.task
|
61
|
-
@gui["cbShouldSync"].active = Knj::Strings.yn_str(@timelog[:sync_need], true, false)
|
62
|
-
@gui["cbTravelFixed"].active = Knj::Strings.yn_str(@timelog[:travelfixed], true, false)
|
63
|
-
@gui["cbWorkInternal"].active = Knj::Strings.yn_str(@timelog[:workinternal], true, false)
|
64
|
-
@gui["cbTimeType"].sel = @timelog[:timetype]
|
65
|
-
@gui["txtTimestamp"].text = Knj::Datet.in(@timelog[:timestamp]).out
|
66
|
-
else
|
67
|
-
@gui["btnRemove"].visible = false
|
68
|
-
@gui["txtTimestamp"].text = Knj::Datet.new.out
|
69
|
-
end
|
70
|
-
|
71
|
-
#Show the window.
|
72
|
-
@gui["window"].show
|
73
|
-
end
|
74
|
-
|
75
|
-
def on_btnSave_clicked(*args)
|
76
|
-
#Generate task-ID based on widget-value.
|
77
|
-
task = @gui["cbTask"].sel
|
78
|
-
if task.respond_to?(:is_knj?)
|
79
|
-
task_id = task.id
|
80
|
-
else
|
81
|
-
task_id = 0
|
82
|
-
end
|
83
|
-
|
84
|
-
#Get times as integers based on widget-values.
|
85
|
-
if @gui["txtTime"].text == ""
|
86
|
-
time_secs = 0
|
87
|
-
else
|
88
|
-
begin
|
89
|
-
time_secs = Knj::Strings.human_time_str_to_secs(@gui["txtTime"].text)
|
90
|
-
rescue => e
|
91
|
-
Knj::Gtk2.msgbox(_("You have entered an invalid time-format.") + "\n\n" + Knj::Errors.error_str(e))
|
92
|
-
return nil
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
if @gui["txtTimeTransport"].text == ""
|
97
|
-
time_transport_secs = 0
|
98
|
-
else
|
99
|
-
begin
|
100
|
-
time_transport_secs = Knj::Strings.human_time_str_to_secs(@gui["txtTimeTransport"].text)
|
101
|
-
rescue => e
|
102
|
-
Knj::Gtk2.msgbox(_("You have entered an invalid transport-time-format.") + "\n\n" + Knj::Errors.error_str(e))
|
103
|
-
return nil
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
begin
|
108
|
-
timestamp_dbstr = Knj::Datet.in(@gui["txtTimestamp"].text).dbstr
|
109
|
-
rescue
|
110
|
-
Knj::Gtk2.msgbox(_("You have entered an invalid timestamp."))
|
111
|
-
return nil
|
112
|
-
end
|
113
|
-
|
114
|
-
#Generate hash for updating dataabase.
|
115
|
-
save_hash = {
|
116
|
-
:descr => @gui["txtDescr"].text,
|
117
|
-
:timestamp => timestamp_dbstr,
|
118
|
-
:time => time_secs,
|
119
|
-
:timetype => @gui["cbTimeType"].sel,
|
120
|
-
:time_transport => time_transport_secs,
|
121
|
-
:transportdescription => @gui["txtTransportDescr"].text,
|
122
|
-
:transportlength => Knj::Locales.number_in(@gui["txtTransportLength"].text),
|
123
|
-
:transportcosts => Knj::Locales.number_in(@gui["txtTransportCosts"].text),
|
124
|
-
:task_id => task_id,
|
125
|
-
:sync_need => Knj::Strings.yn_str(@gui["cbShouldSync"].active?, 1, 0),
|
126
|
-
:workinternal => Knj::Strings.yn_str(@gui["cbWorkInternal"].active?, 1, 0),
|
127
|
-
:travelfixed => Knj::Strings.yn_str(@gui["cbTravelFixed"].active?, 1, 0)
|
128
|
-
}
|
129
|
-
|
130
|
-
#Update or add the timelog.
|
131
|
-
if @timelog
|
132
|
-
@timelog.update(save_hash)
|
133
|
-
else
|
134
|
-
@timelog = @args[:oata].ob.add(:Timelog, save_hash)
|
135
|
-
end
|
136
|
-
|
137
|
-
#Start tracking the current timelog if the checkbox has been checked.
|
138
|
-
if @gui["cbStartTracking"].active?
|
139
|
-
@args[:oata].timelog_active = @timelog
|
140
|
-
end
|
141
|
-
|
142
|
-
@gui["window"].destroy
|
143
|
-
end
|
144
|
-
|
145
|
-
def on_btnRemove_clicked(*args)
|
146
|
-
if Knj::Gtk2.msgbox(_("Do you want to remove this timelog? This will not delete the timelog on OpenAll."), "yesno") != "yes"
|
147
|
-
return nil
|
148
|
-
end
|
149
|
-
|
150
|
-
@args[:oata].ob.delete(@timelog)
|
151
|
-
@gui["window"].destroy
|
152
|
-
end
|
153
|
-
end
|