openall_time_applet 0.0.38 → 0.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +2 -0
- data/Gemfile.lock +25 -17
- data/VERSION +1 -1
- data/conf/db_schema.rb +3 -1
- data/glade/win_main.glade +15 -6
- data/gui/trayicon.rb +3 -5
- data/gui/win_main.rb +403 -189
- data/gui/win_preferences.rb +9 -1
- data/lib/openall_time_applet.rb +79 -20
- data/locales/da_DK/LC_MESSAGES/default.mo +0 -0
- data/locales/da_DK/LC_MESSAGES/default.po +89 -73
- data/models/task.rb +62 -3
- data/models/timelog.rb +30 -0
- data/openall_time_applet.gemspec +14 -8
- metadata +35 -15
data/gui/win_main.rb
CHANGED
@@ -1,29 +1,64 @@
|
|
1
1
|
class Openall_time_applet::Gui::Win_main
|
2
|
+
ROWS_BOLD = [:timestamp, :time, :descr, :ttime, :tkm, :ttype, :tdescr, :cost, :task]
|
3
|
+
|
2
4
|
attr_reader :args, :gui
|
3
5
|
|
4
6
|
def initialize(args)
|
5
7
|
@args = args
|
8
|
+
@oata = @args[:oata]
|
9
|
+
@ob = @oata.ob
|
10
|
+
@log = @oata.log
|
6
11
|
|
7
12
|
@gui = Gtk::Builder.new.add("#{File.dirname(__FILE__)}/../glade/win_main.glade")
|
8
13
|
@gui.translate
|
9
14
|
@gui.connect_signals{|h| method(h)}
|
10
|
-
|
15
|
+
|
16
|
+
#Shortcut-variables to very used widgets.
|
17
|
+
@window = @gui["window"]
|
18
|
+
@expander = @gui["expOverview"]
|
19
|
+
@tv = @gui["tvTimelogs"]
|
20
|
+
@tvpt = @gui["tvTimelogsPrepareTransfer"]
|
21
|
+
|
22
|
+
|
23
|
+
#Set icon for window.
|
24
|
+
@window.icon = "#{File.dirname(__FILE__)}/../gfx/icon_time_black.png"
|
11
25
|
|
12
26
|
|
27
|
+
#Settings for various widgets.
|
28
|
+
Gtk2_expander_settings.new(:expander => @expander, :name => "main_expander", :db => @oata.db)
|
29
|
+
Gtk2_window_settings.new(:window => @window, :name => "main_window", :db => @oata.db)
|
30
|
+
|
31
|
+
#Trigger max. height stuff.
|
32
|
+
self.on_expOverview_activate(@expander)
|
33
|
+
|
13
34
|
#Generate list-store containing tasks for the task-column.
|
14
|
-
task_ls = Gtk::ListStore.new(String, String)
|
15
|
-
|
35
|
+
@task_ls = Gtk::ListStore.new(String, String)
|
36
|
+
|
37
|
+
iter = @task_ls.append
|
16
38
|
iter[0] = _("None")
|
17
|
-
iter[1] = 0
|
39
|
+
iter[1] = "0"
|
18
40
|
|
19
41
|
tasks = [_("Choose:")]
|
20
|
-
@
|
21
|
-
iter = task_ls.append
|
22
|
-
iter[0] = task
|
42
|
+
@ob.static(:Task, :tasks_to_show) do |task|
|
43
|
+
iter = @task_ls.append
|
44
|
+
iter[0] = task.name
|
23
45
|
iter[1] = task.id.to_s
|
24
46
|
tasks << task
|
25
47
|
end
|
26
48
|
|
49
|
+
self.task_ls_resort
|
50
|
+
@gui["cbTask"].init(tasks)
|
51
|
+
|
52
|
+
|
53
|
+
#Generate list-store containing time-types.
|
54
|
+
@time_types = Openall_time_applet::Models::Timelog.time_types
|
55
|
+
time_types_ls = Gtk::ListStore.new(String, String)
|
56
|
+
@time_types.each do |key, val|
|
57
|
+
iter = time_types_ls.append
|
58
|
+
iter[0] = val
|
59
|
+
iter[1] = key
|
60
|
+
end
|
61
|
+
|
27
62
|
|
28
63
|
#Set up completion for description entry.
|
29
64
|
@descr_ec = Gtk::EntryCompletion.new
|
@@ -35,11 +70,10 @@ class Openall_time_applet::Gui::Win_main
|
|
35
70
|
|
36
71
|
|
37
72
|
|
38
|
-
|
39
|
-
@gui["cbTask"].init(tasks)
|
40
|
-
|
41
|
-
init_data = @gui["tvTimelogs"].init(
|
73
|
+
init_data = @tv.init(
|
42
74
|
:type => :treestore,
|
75
|
+
:reorderable => false,
|
76
|
+
:sortable => false,
|
43
77
|
:cols => [
|
44
78
|
_("ID"),
|
45
79
|
{
|
@@ -79,6 +113,14 @@ class Openall_time_applet::Gui::Win_main
|
|
79
113
|
:expand => true,
|
80
114
|
:fixed_width => 160
|
81
115
|
},
|
116
|
+
{
|
117
|
+
:title => _("T-type"),
|
118
|
+
:type => :combo,
|
119
|
+
:model => time_types_ls,
|
120
|
+
:has_entry => false,
|
121
|
+
:fixed_width => 120,
|
122
|
+
:markup => true
|
123
|
+
},
|
82
124
|
{
|
83
125
|
:title => _("Cost"),
|
84
126
|
:type => :string,
|
@@ -90,14 +132,14 @@ class Openall_time_applet::Gui::Win_main
|
|
90
132
|
:expand => false
|
91
133
|
},
|
92
134
|
{
|
93
|
-
:title => _("
|
135
|
+
:title => _("Internal")[0, 3] + ".",
|
94
136
|
:type => :toggle,
|
95
137
|
:expand => false
|
96
138
|
},
|
97
139
|
{
|
98
140
|
:title => _("Task"),
|
99
141
|
:type => :combo,
|
100
|
-
:model => task_ls,
|
142
|
+
:model => @task_ls,
|
101
143
|
:has_entry => false,
|
102
144
|
:markup => true,
|
103
145
|
:expand => true,
|
@@ -112,8 +154,7 @@ class Openall_time_applet::Gui::Win_main
|
|
112
154
|
)
|
113
155
|
|
114
156
|
@tv_settings = Gtk2_treeview_settings.new(
|
115
|
-
:
|
116
|
-
:tv => @gui["tvTimelogs"],
|
157
|
+
:tv => @tv,
|
117
158
|
:col_ids => {
|
118
159
|
0 => :id,
|
119
160
|
1 => :timestamp,
|
@@ -122,21 +163,22 @@ class Openall_time_applet::Gui::Win_main
|
|
122
163
|
4 => :ttime,
|
123
164
|
5 => :tkm,
|
124
165
|
6 => :tdescr,
|
125
|
-
7 => :
|
126
|
-
8 => :
|
127
|
-
9 => :
|
128
|
-
10 => :
|
129
|
-
11 => :
|
166
|
+
7 => :ttype,
|
167
|
+
8 => :cost,
|
168
|
+
9 => :fixed,
|
169
|
+
10 => :int,
|
170
|
+
11 => :task,
|
171
|
+
12 => :track
|
130
172
|
}
|
131
173
|
)
|
132
174
|
|
133
175
|
Knj::Gtk2::Tv.editable_text_renderers_to_model(
|
134
|
-
:ob => @
|
135
|
-
:tv => @
|
176
|
+
:ob => @oata.ob,
|
177
|
+
:tv => @tv,
|
136
178
|
:model_class => :Timelog,
|
137
179
|
:renderers => init_data[:renderers],
|
138
180
|
:change_before => proc{|d|
|
139
|
-
if d[:col_no] == 2 and @
|
181
|
+
if d[:col_no] == 2 and @oata.timelog_active and @oata.timelog_active.id == d[:model].id
|
140
182
|
raise _("You cannot edit the time for the active timelog.")
|
141
183
|
end
|
142
184
|
|
@@ -152,53 +194,64 @@ class Openall_time_applet::Gui::Win_main
|
|
152
194
|
@tv_editting = nil
|
153
195
|
},
|
154
196
|
:cols => {
|
155
|
-
|
197
|
+
@tv_settings.col_orig_no_for_id(:timestamp) => {
|
156
198
|
:col => :timestamp,
|
157
199
|
:value_callback => self.method(:tv_editable_timestamp_callback),
|
158
200
|
:value_set_callback => self.method(:tv_editable_timestamp_set_callback)
|
159
201
|
},
|
160
|
-
|
202
|
+
@tv_settings.col_orig_no_for_id(:time) => {
|
161
203
|
:col => :time,
|
162
204
|
:value_callback => proc{ |data| Knj::Strings.human_time_str_to_secs(data[:value]) },
|
163
205
|
:value_set_callback => proc{ |data| Knj::Strings.secs_to_human_time_str(data[:value], :secs => false) }
|
164
206
|
},
|
165
|
-
|
166
|
-
|
207
|
+
@tv_settings.col_orig_no_for_id(:descr) => :descr,
|
208
|
+
@tv_settings.col_orig_no_for_id(:ttime) => {
|
167
209
|
:col => :time_transport,
|
168
210
|
:value_callback => proc{ |data| Knj::Strings.human_time_str_to_secs(data[:value]) },
|
169
211
|
:value_set_callback => proc{ |data| Knj::Strings.secs_to_human_time_str(data[:value], :secs => false) }
|
170
212
|
},
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
213
|
+
@tv_settings.col_orig_no_for_id(:tkm) => {:col => :transportlength, :type => :int},
|
214
|
+
@tv_settings.col_orig_no_for_id(:tdescr) => {:col => :transportdescription},
|
215
|
+
@tv_settings.col_orig_no_for_id(:ttype) => {
|
216
|
+
:col => :timetype,
|
217
|
+
:value_callback => lambda{|data|
|
218
|
+
@time_types.key(data[:value])
|
219
|
+
},
|
220
|
+
:value_set_callback => proc{|data|
|
221
|
+
Knj::Web.html(@time_types.fetch(data[:value]))
|
222
|
+
}
|
223
|
+
},
|
224
|
+
@tv_settings.col_orig_no_for_id(:cost) => {:col => :transportcosts, :type => :human_number, :decimals => 2},
|
225
|
+
@tv_settings.col_orig_no_for_id(:fixed) => {:col => :travelfixed},
|
226
|
+
@tv_settings.col_orig_no_for_id(:int) => {:col => :workinternal},
|
227
|
+
@tv_settings.col_orig_no_for_id(:task) => {
|
177
228
|
:col => :task_id,
|
178
229
|
:value_callback => lambda{|data|
|
179
|
-
task
|
180
|
-
|
181
|
-
|
182
|
-
return 0
|
183
|
-
else
|
184
|
-
return task.id
|
230
|
+
#Return ID of the found task or 0 if none was found.
|
231
|
+
@ob.list(:Task) do |task|
|
232
|
+
return task.id if task.name == data[:value]
|
185
233
|
end
|
234
|
+
|
235
|
+
return 0
|
186
236
|
},
|
187
|
-
:value_set_callback => proc{|data|
|
237
|
+
:value_set_callback => proc{|data|
|
238
|
+
#Return the task-name for the current rows timelog.
|
239
|
+
data[:model].task_name
|
240
|
+
}
|
188
241
|
},
|
189
|
-
|
242
|
+
@tv_settings.col_orig_no_for_id(:track) => {
|
190
243
|
:value_callback => lambda{|data|
|
191
244
|
if !data[:model]
|
192
245
|
Knj::Gtk2.msgbox(_("You cannot track a date. Please track a timelog instead."))
|
193
246
|
return false
|
194
247
|
else
|
195
248
|
if data[:value]
|
196
|
-
@
|
197
|
-
elsif data[:model] == @
|
198
|
-
@
|
249
|
+
@oata.timelog_active = data[:model]
|
250
|
+
elsif data[:model] == @oata.timelog_active
|
251
|
+
@oata.timelog_stop_tracking
|
199
252
|
end
|
200
253
|
|
201
|
-
return data[:model] == @
|
254
|
+
return data[:model] == @oata.timelog_active
|
202
255
|
end
|
203
256
|
}
|
204
257
|
}
|
@@ -207,11 +260,20 @@ class Openall_time_applet::Gui::Win_main
|
|
207
260
|
|
208
261
|
|
209
262
|
#The ID column should not be visible (it is only used to identify which timelog the row represents).
|
210
|
-
@
|
263
|
+
@tv.columns[0].visible = false
|
211
264
|
|
212
265
|
|
213
266
|
#Move the columns around to the right order (the way Jacob wanted them).
|
214
|
-
@
|
267
|
+
@tv.move_column_after(@tv.columns[10], @tv.columns[3])
|
268
|
+
@tv.move_column_after(@tv.columns[11], @tv.columns[3])
|
269
|
+
@tv.move_column_after(@tv.columns[11], @tv.columns[5])
|
270
|
+
@tv.move_column_after(@tv.columns[9], @tv.columns[6])
|
271
|
+
@tv.move_column_after(@tv.columns[11], @tv.columns[8])
|
272
|
+
|
273
|
+
|
274
|
+
#When a new row is selected, is should be evaluated if the minus-button should be active or not.
|
275
|
+
@tv.selection.signal_connect("changed", &self.method(:validate_minus_active))
|
276
|
+
self.validate_minus_active
|
215
277
|
|
216
278
|
|
217
279
|
#Connect certain column renderers to the editingStarted-method, so editing can be canceled, if the user tries to edit forbidden data on the active timelog.
|
@@ -223,8 +285,10 @@ class Openall_time_applet::Gui::Win_main
|
|
223
285
|
|
224
286
|
|
225
287
|
#Reload the treeview if something happened to a timelog.
|
226
|
-
@reload_id = @
|
227
|
-
@
|
288
|
+
@reload_id = @ob.connect("object" => :Timelog, "signals" => ["add", "update"], &self.method(:reload_timelogs))
|
289
|
+
@reload_id_delete = @ob.connect("object" => :Timelog, "signals" => ["delete"], &self.method(:on_timelog_delete))
|
290
|
+
@reload_id_update = @ob.connect("object" => :Timelog, "signals" => ["update"], &self.method(:on_timelog_update))
|
291
|
+
@reload_tasks_id = @ob.connect("object" => :Task, "signals" => ["add"], &self.method(:on_task_added))
|
228
292
|
|
229
293
|
|
230
294
|
#Update switch-button.
|
@@ -232,40 +296,43 @@ class Openall_time_applet::Gui::Win_main
|
|
232
296
|
|
233
297
|
|
234
298
|
#Update switch-button when active timelog is changed.
|
235
|
-
@event_timelog_active_changed = @
|
299
|
+
@event_timelog_active_changed = @oata.events.connect(:timelog_active_changed, &self.method(:on_timelog_active_changed))
|
236
300
|
|
237
301
|
|
238
302
|
#This timeout controls the updating of the timelog-info-frame and the time-counter for the active timelog in the treeview.
|
239
303
|
@timeout_id = Gtk.timeout_add(1000, &self.method(:timeout_update_sec))
|
240
|
-
|
304
|
+
self.timeout_update_sec if @oata.timelog_active
|
241
305
|
|
242
306
|
|
243
307
|
#Initializes sync-box.
|
244
|
-
|
308
|
+
lab_transfer = _("Transfer")
|
309
|
+
lab_transfer = "#{lab_transfer[0, 1]}_#{lab_transfer[1, 99]}" #For 'r'-shortcut.
|
310
|
+
@gui["btnSyncPrepareTransfer"].label = lab_transfer
|
311
|
+
|
245
312
|
|
246
313
|
#Generate list-store containing tasks for the task-column.
|
247
|
-
task_ls = Gtk::ListStore.new(String, String)
|
248
|
-
iter = task_ls.append
|
314
|
+
@task_ls = Gtk::ListStore.new(String, String)
|
315
|
+
iter = @task_ls.append
|
249
316
|
iter[0] = _("None")
|
250
317
|
iter[1] = 0.to_s
|
251
318
|
|
252
319
|
tasks = [_("Choose:")]
|
253
|
-
@
|
254
|
-
iter = task_ls.append
|
255
|
-
iter[0] = task
|
320
|
+
@ob.static(:Task, :tasks_to_show) do |task|
|
321
|
+
iter = @task_ls.append
|
322
|
+
iter[0] = task.name
|
256
323
|
iter[1] = task.id.to_s
|
257
324
|
tasks << task
|
258
325
|
end
|
259
326
|
|
260
327
|
#Initialize timelog treeview.
|
261
|
-
init_data = Knj::Gtk2::Tv.init(@
|
328
|
+
init_data = Knj::Gtk2::Tv.init(@tvpt, [
|
262
329
|
_("ID"),
|
263
330
|
{
|
264
331
|
:title => _("Description"),
|
265
332
|
:type => :string,
|
266
333
|
:expand => true
|
267
334
|
},
|
268
|
-
_("
|
335
|
+
_("Stamp"),
|
269
336
|
_("Time"),
|
270
337
|
_("T-time"),
|
271
338
|
_("T-km"),
|
@@ -280,7 +347,7 @@ class Openall_time_applet::Gui::Win_main
|
|
280
347
|
:type => :toggle
|
281
348
|
},
|
282
349
|
{
|
283
|
-
:title => _("Internal"),
|
350
|
+
:title => _("Internal")[0, 3] + ".",
|
284
351
|
:type => :toggle
|
285
352
|
},
|
286
353
|
{
|
@@ -290,7 +357,7 @@ class Openall_time_applet::Gui::Win_main
|
|
290
357
|
{
|
291
358
|
:title => _("Task"),
|
292
359
|
:type => :combo,
|
293
|
-
:model => task_ls,
|
360
|
+
:model => @task_ls,
|
294
361
|
:has_entry => false,
|
295
362
|
:expand => true
|
296
363
|
},
|
@@ -299,7 +366,7 @@ class Openall_time_applet::Gui::Win_main
|
|
299
366
|
|
300
367
|
@tv_settings_pt = Gtk2_treeview_settings.new(
|
301
368
|
:id => "win_main_tvTimelogsPrepareTransfer",
|
302
|
-
:tv => @
|
369
|
+
:tv => @tvpt,
|
303
370
|
:col_ids => {
|
304
371
|
0 => :id,
|
305
372
|
1 => :descr,
|
@@ -317,13 +384,16 @@ class Openall_time_applet::Gui::Win_main
|
|
317
384
|
}
|
318
385
|
)
|
319
386
|
|
320
|
-
@
|
321
|
-
@
|
387
|
+
@tvpt.move_column_after(@tvpt.columns[1], @tvpt.columns[3])
|
388
|
+
@tvpt.move_column_after(@tvpt.columns[11], @tvpt.columns[3])
|
389
|
+
@tvpt.move_column_after(@tvpt.columns[9], @tvpt.columns[4])
|
390
|
+
@tvpt.move_column_after(@tvpt.columns[10], @tvpt.columns[5])
|
391
|
+
@tvpt.move_column_after(@tvpt.columns[9], @tvpt.columns[6])
|
322
392
|
|
323
393
|
#Make columns editable.
|
324
394
|
Knj::Gtk2::Tv.editable_text_renderers_to_model(
|
325
|
-
:ob => @
|
326
|
-
:tv => @
|
395
|
+
:ob => @oata.ob,
|
396
|
+
:tv => @tvpt,
|
327
397
|
:model_class => :Timelog,
|
328
398
|
:renderers => init_data[:renderers],
|
329
399
|
:change_before => proc{ @dont_reload_sync = true },
|
@@ -337,17 +407,79 @@ class Openall_time_applet::Gui::Win_main
|
|
337
407
|
}
|
338
408
|
}
|
339
409
|
)
|
340
|
-
@
|
410
|
+
@tvpt.columns[0].visible = false
|
341
411
|
@gui["vboxPrepareTransfer"].hide
|
342
|
-
@reload_preparetransfer_id = @
|
412
|
+
@reload_preparetransfer_id = @ob.connect("object" => :Timelog, "signals" => ["add", "update"], &self.method(:reload_timelogs_preparetransfer))
|
343
413
|
|
344
414
|
|
345
415
|
|
346
416
|
#Show the window.
|
347
|
-
@
|
417
|
+
@window.show
|
348
418
|
self.timelog_info_trigger
|
349
|
-
width = @
|
350
|
-
@
|
419
|
+
width = @window.size[0]
|
420
|
+
@window.resize(width, 1)
|
421
|
+
end
|
422
|
+
|
423
|
+
def window_resize_height_disable
|
424
|
+
hints = Gdk::Geometry.new
|
425
|
+
|
426
|
+
hints.min_width = 1
|
427
|
+
hints.max_width = 9999
|
428
|
+
|
429
|
+
hints.min_height = 1
|
430
|
+
hints.max_height = 1
|
431
|
+
|
432
|
+
@window.set_geometry_hints(@expander, hints, Gdk::Window::HINT_MAX_SIZE)
|
433
|
+
end
|
434
|
+
|
435
|
+
def window_resize_height_enable
|
436
|
+
hints = Gdk::Geometry.new
|
437
|
+
|
438
|
+
hints.min_width = 1
|
439
|
+
hints.max_width = 9999
|
440
|
+
|
441
|
+
hints.min_height = 1
|
442
|
+
hints.max_height = 9999
|
443
|
+
|
444
|
+
@window.set_geometry_hints(@expander, hints, Gdk::Window::HINT_MAX_SIZE)
|
445
|
+
end
|
446
|
+
|
447
|
+
def task_ls_resort
|
448
|
+
@task_ls.set_sort_column_id(0)
|
449
|
+
@task_ls.set_sort_func(0, &lambda{|iter1, iter2|
|
450
|
+
task_id_1 = iter1[1].to_i
|
451
|
+
task_id_2 = iter2[1].to_i
|
452
|
+
|
453
|
+
task_name_1 = iter1[0].to_s.downcase
|
454
|
+
task_name_2 = iter2[0].to_s.downcase
|
455
|
+
|
456
|
+
if task_id_1 == 0
|
457
|
+
return -1
|
458
|
+
elsif task_id_2 == 0
|
459
|
+
return 1
|
460
|
+
else
|
461
|
+
return task_name_1 <=> task_name_2
|
462
|
+
end
|
463
|
+
})
|
464
|
+
end
|
465
|
+
|
466
|
+
#Called after a new task has been added.
|
467
|
+
def on_task_added(task)
|
468
|
+
puts "New task added: #{task.to_hash}"
|
469
|
+
|
470
|
+
#Add the new task to the treeview rows.
|
471
|
+
iter = @task_ls.append
|
472
|
+
iter[0] = task.name
|
473
|
+
iter[1] = task.id.to_s
|
474
|
+
|
475
|
+
self.task_ls_resort
|
476
|
+
|
477
|
+
renderer = @tv_settings.cellrenderer_for_id(:task)
|
478
|
+
renderer.model = @task_ls
|
479
|
+
|
480
|
+
#Add the new task to the combobox in the top.
|
481
|
+
@gui["cbTask"].append_model(:model => task)
|
482
|
+
@gui["cbTask"].resort
|
351
483
|
end
|
352
484
|
|
353
485
|
#This is called when an item from the description-entry-completion-menu is selected. This method sets the selected text in the description-entry.
|
@@ -394,13 +526,13 @@ class Openall_time_applet::Gui::Win_main
|
|
394
526
|
added = {}
|
395
527
|
@descr_ec.model.clear
|
396
528
|
|
397
|
-
@
|
529
|
+
@ob.list(:Worktime, "orderby" => [["timestamp", "desc"]]) do |worktime|
|
398
530
|
next if added.key?(worktime[:comment])
|
399
531
|
added[worktime[:comment]] = true
|
400
532
|
@descr_ec.model.append[0] = worktime[:comment]
|
401
533
|
end
|
402
534
|
|
403
|
-
@
|
535
|
+
@ob.list(:Timelog, "orderby" => [["timestamp", "desc"]]) do |timelog|
|
404
536
|
next if added.key?(timelog[:descr])
|
405
537
|
added[timelog[:descr]] = true
|
406
538
|
@descr_ec.model.append[0] = timelog[:descr]
|
@@ -408,57 +540,63 @@ class Openall_time_applet::Gui::Win_main
|
|
408
540
|
end
|
409
541
|
|
410
542
|
def reload_timelogs_preparetransfer
|
411
|
-
return nil if @dont_reload_sync or @
|
412
|
-
@
|
413
|
-
@timelogs_sync_count = 0
|
414
|
-
tnow_str = Time.now.strftime("%Y %m %d")
|
543
|
+
return nil if @dont_reload_sync or @tvpt.destroyed?
|
544
|
+
@dont_reload_sync = true
|
415
545
|
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
#If transport is logged, then the work if offsite. It should be rounded up by 30 min. Else 15 min. round up.
|
422
|
-
if transport > 0
|
423
|
-
roundup = 1800
|
424
|
-
else
|
425
|
-
roundup = 900
|
426
|
-
end
|
427
|
-
|
428
|
-
#Do the actual counting.
|
429
|
-
count_rounded_time = 0
|
430
|
-
loop do
|
431
|
-
break if count_rounded_time >= time
|
432
|
-
count_rounded_time += roundup
|
433
|
-
end
|
434
|
-
|
435
|
-
#Set sync-time on timelog.
|
436
|
-
timelog[:time_sync] = count_rounded_time
|
437
|
-
|
438
|
-
tstamp = timelog.timestamp
|
546
|
+
begin
|
547
|
+
@tvpt.model.clear
|
548
|
+
@timelogs_sync_count = 0
|
549
|
+
tnow_str = Time.now.strftime("%Y %m %d")
|
439
550
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
551
|
+
@ob.list(:Timelog, "task_id_not" => ["", 0], "orderby" => [["timestamp", "desc"]]) do |timelog|
|
552
|
+
#Read time and transport from timelog.
|
553
|
+
time = timelog[:time].to_i
|
554
|
+
transport = timelog[:time_transport].to_i
|
555
|
+
|
556
|
+
#If transport is logged, then the work if offsite. It should be rounded up by 30 min. Else 15 min. round up.
|
557
|
+
if transport > 0
|
558
|
+
roundup = 1800
|
559
|
+
else
|
560
|
+
roundup = 900
|
561
|
+
end
|
562
|
+
|
563
|
+
#Do the actual counting.
|
564
|
+
count_rounded_time = 0
|
565
|
+
loop do
|
566
|
+
break if count_rounded_time >= time
|
567
|
+
count_rounded_time += roundup
|
568
|
+
end
|
569
|
+
|
570
|
+
#Set sync-time on timelog.
|
571
|
+
timelog[:time_sync] = count_rounded_time
|
572
|
+
|
573
|
+
tstamp = timelog.timestamp
|
574
|
+
|
575
|
+
if tstamp.strftime("%Y %m %d") == tnow_str
|
576
|
+
tstamp_str = tstamp.strftime("%H:%M")
|
577
|
+
else
|
578
|
+
tstamp_str = tstamp.strftime("%d/%m")
|
579
|
+
end
|
580
|
+
|
581
|
+
@tv_settings_pt.append(
|
582
|
+
:id => timelog.id,
|
583
|
+
:descr => timelog[:descr],
|
584
|
+
:timestamp => tstamp_str,
|
585
|
+
:time => timelog.time_as_human,
|
586
|
+
:ttime => timelog.time_transport_as_human,
|
587
|
+
:tkm => Knj::Locales.number_out(timelog[:transportlength], 0),
|
588
|
+
:tdescr => timelog.transport_descr_short,
|
589
|
+
:cost => Knj::Locales.number_out(timelog[:transportcosts], 2),
|
590
|
+
:fixed => Knj::Strings.yn_str(timelog[:travelfixed], true, false),
|
591
|
+
:internal => Knj::Strings.yn_str(timelog[:workinternal], true, false),
|
592
|
+
:skip => Knj::Strings.yn_str(timelog[:sync_need], false, true),
|
593
|
+
:task => timelog.task_name,
|
594
|
+
:sync_time => Knj::Strings.secs_to_human_time_str(count_rounded_time, :secs => false)
|
595
|
+
)
|
596
|
+
@timelogs_sync_count += 1
|
444
597
|
end
|
445
|
-
|
446
|
-
@
|
447
|
-
:id => timelog.id,
|
448
|
-
:descr => timelog[:descr],
|
449
|
-
:timestamp => tstamp_str,
|
450
|
-
:time => timelog.time_as_human,
|
451
|
-
:ttime => timelog.time_transport_as_human,
|
452
|
-
:tkm => Knj::Locales.number_out(timelog[:transportlength], 0),
|
453
|
-
:tdescr => timelog.transport_descr_short,
|
454
|
-
:cost => Knj::Locales.number_out(timelog[:transportcosts], 2),
|
455
|
-
:fixed => Knj::Strings.yn_str(timelog[:travelfixed], true, false),
|
456
|
-
:internal => Knj::Strings.yn_str(timelog[:workinternal], true, false),
|
457
|
-
:skip => Knj::Strings.yn_str(timelog[:sync_need], false, true),
|
458
|
-
:task => timelog.task_name,
|
459
|
-
:sync_time => Knj::Strings.secs_to_human_time_str(count_rounded_time, :secs => false)
|
460
|
-
)
|
461
|
-
@timelogs_sync_count += 1
|
598
|
+
ensure
|
599
|
+
@dont_reload_sync = nil
|
462
600
|
end
|
463
601
|
end
|
464
602
|
|
@@ -470,7 +608,7 @@ class Openall_time_applet::Gui::Win_main
|
|
470
608
|
Knj::Gtk2.msgbox("msg" => _("There is nothing to sync at this time."), "run" => false)
|
471
609
|
else
|
472
610
|
#...else show the window.
|
473
|
-
@
|
611
|
+
@expander.hide
|
474
612
|
self.update_sync_totals
|
475
613
|
@gui["vboxPrepareTransfer"].show
|
476
614
|
end
|
@@ -479,13 +617,18 @@ class Openall_time_applet::Gui::Win_main
|
|
479
617
|
def update_sync_totals
|
480
618
|
total_secs = 0
|
481
619
|
|
482
|
-
@
|
483
|
-
time_val = @
|
620
|
+
@tvpt.model.each do |model, path, iter|
|
621
|
+
time_val = @tvpt.model.get_value(iter, 12)
|
484
622
|
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
623
|
+
col_no_skip = @tv_settings_pt.col_orig_no_for_id(:skip)
|
624
|
+
skip_val = @tvpt.model.get_value(iter, col_no_skip)
|
625
|
+
|
626
|
+
if skip_val != 1
|
627
|
+
begin
|
628
|
+
total_secs += Knj::Strings.human_time_str_to_secs(time_val)
|
629
|
+
rescue
|
630
|
+
#ignore - user is properly entering stuff.
|
631
|
+
end
|
489
632
|
end
|
490
633
|
end
|
491
634
|
|
@@ -493,16 +636,16 @@ class Openall_time_applet::Gui::Win_main
|
|
493
636
|
end
|
494
637
|
|
495
638
|
def on_btnCancelPrepareTransfer_clicked
|
496
|
-
@
|
639
|
+
@expander.show
|
497
640
|
@gui["vboxPrepareTransfer"].hide
|
498
641
|
end
|
499
642
|
|
500
643
|
#This method is called, when editting starts in a description-, time- or task-cell. If it is the active timelog, then editting is canceled.
|
501
644
|
def on_cell_editingStarted(renderer, editable, path, col_title)
|
502
|
-
iter = @
|
503
|
-
timelog_id = @
|
645
|
+
iter = @tv.model.get_iter(path)
|
646
|
+
timelog_id = @tv.model.get_value(iter, 0).to_i
|
504
647
|
|
505
|
-
if tlog = @
|
648
|
+
if tlog = @oata.timelog_active and tlog.id.to_i == timelog_id
|
506
649
|
renderer.stop_editing(true)
|
507
650
|
Knj::Gtk2.msgbox(_("You cannot edit this on the active timelog."))
|
508
651
|
end
|
@@ -522,16 +665,19 @@ class Openall_time_applet::Gui::Win_main
|
|
522
665
|
def reload_timelogs
|
523
666
|
self.reload_descr_completion
|
524
667
|
|
525
|
-
return nil if @dont_reload or @
|
668
|
+
return nil if @dont_reload or @tv.destroyed?
|
669
|
+
@log.debug("Reloading main treeview.")
|
670
|
+
|
526
671
|
tnow_str = Time.now.strftime("%Y %m %d")
|
527
|
-
@
|
672
|
+
@tv.model.clear
|
528
673
|
|
529
674
|
#Create date-parent elements that the timelogs will be appended under.
|
530
675
|
dates = {}
|
531
676
|
now_year = Time.now.year
|
532
677
|
|
533
|
-
@
|
678
|
+
@ob.list(:Timelog, "orderby" => [["timestamp", "desc"]]) do |tlog|
|
534
679
|
tstamp = Datet.in(tlog[:timestamp])
|
680
|
+
next if !tstamp
|
535
681
|
str = tstamp.out(:time => false)
|
536
682
|
|
537
683
|
if !dates.key?(str)
|
@@ -554,17 +700,19 @@ class Openall_time_applet::Gui::Win_main
|
|
554
700
|
end
|
555
701
|
|
556
702
|
#Append the timelogs to the parent dates.
|
557
|
-
@
|
703
|
+
@ob.list(:Timelog, "orderby" => ["task_id", "descr", "timestamp"]) do |timelog|
|
558
704
|
begin
|
559
705
|
tstamp_str = timelog.timestamp_str
|
560
706
|
rescue => e
|
561
707
|
tstamp_str = "[#{_("error")}: #{e.message}"
|
562
708
|
end
|
563
709
|
|
564
|
-
tstamp = timelog.timestamp
|
565
|
-
|
566
|
-
|
567
|
-
|
710
|
+
if tstamp = timelog.timestamp
|
711
|
+
tstamp_str = tstamp.strftime("%H:%M")
|
712
|
+
parent = dates[tstamp.out(:time => false)][:iter]
|
713
|
+
else
|
714
|
+
parent = nil
|
715
|
+
end
|
568
716
|
|
569
717
|
@tv_settings.append_adv(
|
570
718
|
:parent => parent,
|
@@ -575,6 +723,7 @@ class Openall_time_applet::Gui::Win_main
|
|
575
723
|
:descr => Knj::Web.html(timelog[:descr]),
|
576
724
|
:ttime => timelog.time_transport_as_human,
|
577
725
|
:tkm => Knj::Locales.number_out(timelog[:transportlength], 0),
|
726
|
+
:ttype => @time_types[timelog[:timetype]],
|
578
727
|
:tdescr => Knj::Web.html(timelog[:transportdescription]),
|
579
728
|
:cost => Knj::Locales.number_out(timelog[:transportcosts], 2),
|
580
729
|
:fixed => Knj::Strings.yn_str(timelog[:travelfixed], true, false),
|
@@ -585,14 +734,14 @@ class Openall_time_applet::Gui::Win_main
|
|
585
734
|
end
|
586
735
|
|
587
736
|
#Make all dates expand their content (timelogs).
|
588
|
-
@
|
737
|
+
@tv.expand_all
|
589
738
|
|
590
739
|
#Reset cache of which rows are set to bold.
|
591
740
|
@bold_rows = {}
|
592
741
|
end
|
593
742
|
|
594
743
|
def timelog_tv_data_by_timelog(timelog)
|
595
|
-
@
|
744
|
+
@tv.model.each do |model, path, iter|
|
596
745
|
timelog_i_id = iter[0].to_i
|
597
746
|
|
598
747
|
if timelog.id.to_i == timelog_i_id
|
@@ -604,14 +753,14 @@ class Openall_time_applet::Gui::Win_main
|
|
604
753
|
end
|
605
754
|
end
|
606
755
|
|
607
|
-
raise sprintf(_("Could not find timelog in treeview: '%s'."), timelog.id)
|
756
|
+
raise Errno::ENOENT, sprintf(_("Could not find timelog in treeview: '%s'."), timelog.id)
|
608
757
|
end
|
609
758
|
|
610
759
|
def date_tv_data_by_datet(datet, args = nil)
|
611
760
|
datet_str = datet.out(:time => false)
|
612
761
|
add_after = nil
|
613
762
|
|
614
|
-
@
|
763
|
+
@tv.model.each do |model, path, iter|
|
615
764
|
#Skip the iter's that are timelogs (we look for a parent-date).
|
616
765
|
timelog_id = iter[0].to_i
|
617
766
|
next if timelog_id != 0
|
@@ -633,7 +782,7 @@ class Openall_time_applet::Gui::Win_main
|
|
633
782
|
end
|
634
783
|
|
635
784
|
if args and args[:add]
|
636
|
-
iter = @
|
785
|
+
iter = @tv.insert_after(nil, add_after)
|
637
786
|
iter[1] = "<b>#{Knj::Web.html(datet.out(:time => false))}</b>"
|
638
787
|
|
639
788
|
return {
|
@@ -654,18 +803,26 @@ class Openall_time_applet::Gui::Win_main
|
|
654
803
|
parent_date = Php4r.strip_tags(parent_iter[1])
|
655
804
|
|
656
805
|
#Get the date from the selected timelog.
|
657
|
-
tlog_date_str = timelog.timestamp.out(:time => false)
|
806
|
+
tlog_date_str = timelog.timestamp.out(:time => false, :year => false)
|
658
807
|
|
659
808
|
#The date of the timelog has been updated, and the timelog has to be moved elsewhere in the treeview.
|
660
809
|
if parent_date != tlog_date_str
|
661
810
|
#Wait 5 miliseconds so the 'dont_reload' variable wont be 'true' any more.
|
662
811
|
Gtk.timeout_add(5) do
|
812
|
+
@log.debug("Timestamps wasnt the same - reload treeview (parent: #{parent_date} vs tlog: #{tlog_date_str}).")
|
813
|
+
|
663
814
|
#Reload timelogs to make the changed timelog appear under the right date.
|
664
815
|
self.reload_timelogs
|
665
816
|
|
666
817
|
#Re-select the timelog in the treeview.
|
667
|
-
|
668
|
-
|
818
|
+
begin
|
819
|
+
if !timelog.deleted?
|
820
|
+
tlog_data = self.timelog_tv_data_by_timelog(timelog)
|
821
|
+
@tv.selection.select_iter(tlog_data[:iter])
|
822
|
+
end
|
823
|
+
rescue Errno::ENOENT
|
824
|
+
#Ignore - it has been deleted.
|
825
|
+
end
|
669
826
|
|
670
827
|
#Return false for the timeout, so it wont be called again.
|
671
828
|
false
|
@@ -673,13 +830,38 @@ class Openall_time_applet::Gui::Win_main
|
|
673
830
|
end
|
674
831
|
end
|
675
832
|
|
833
|
+
#This method handels events for when a timelog is deleted. It removes the timelog from various treeviews, so it isnt necessary to do a complete reload of them, which takes a lot longer.
|
834
|
+
def on_timelog_delete(timelog)
|
835
|
+
del_id = timelog.id.to_i
|
836
|
+
|
837
|
+
@tv.model.each do |model, path, iter|
|
838
|
+
timelog_id = model.get_value(iter, 0).to_i
|
839
|
+
next if timelog_id <= 0
|
840
|
+
|
841
|
+
if timelog_id == del_id
|
842
|
+
model.remove(iter)
|
843
|
+
break
|
844
|
+
end
|
845
|
+
end
|
846
|
+
|
847
|
+
@tvpt.model.each do |model, path, iter|
|
848
|
+
timelog_id = model.get_value(iter, 0).to_i
|
849
|
+
next if timelog_id <= 0
|
850
|
+
|
851
|
+
if timelog_id == del_id
|
852
|
+
model.remove(iter)
|
853
|
+
break
|
854
|
+
end
|
855
|
+
end
|
856
|
+
end
|
857
|
+
|
676
858
|
#Called when the quit-menu-item is activated.
|
677
859
|
def on_imiQuit_activate
|
678
860
|
#Check if a timelog needs to be synced. If so the user needs to confirm he really wants to quit.
|
679
861
|
timelog_found = nil
|
680
862
|
do_destroy = true
|
681
863
|
|
682
|
-
@
|
864
|
+
@ob.list(:Timelog, "task_id_not" => ["", 0]) do |timelog|
|
683
865
|
if timelog.time_total > 0 or timelog.time_total(:transport => true) > 0 or timelog[:sync_need].to_i == 1
|
684
866
|
timelog_found = timelog
|
685
867
|
break
|
@@ -692,55 +874,54 @@ class Openall_time_applet::Gui::Win_main
|
|
692
874
|
end
|
693
875
|
end
|
694
876
|
|
695
|
-
@
|
877
|
+
@oata.destroy if do_destroy
|
696
878
|
end
|
697
879
|
|
698
880
|
def on_imiPreferences_activate
|
699
|
-
@
|
881
|
+
@oata.show_preferences
|
700
882
|
end
|
701
883
|
|
702
884
|
def on_imiWeekview_activate
|
703
|
-
@
|
885
|
+
@oata.show_worktime_overview
|
704
886
|
end
|
705
887
|
|
706
888
|
def on_window_destroy
|
707
889
|
#Unconnect reload-event. Else it will crash on call to destroyed object. Also frees up various ressources.
|
708
|
-
@
|
709
|
-
@
|
710
|
-
@args[:oata].ob.unconnect("object" => :Timelog, "conn_id" => @reload_preparetransfer_id)
|
890
|
+
@ob.unconnect("object" => :Timelog, "conn_ids" => [@reload_id, @reload_id_update, @reload_id_delete, @reload_preparetransfer_id])
|
891
|
+
@ob.unconnect("object" => :Task, "conn_ids" => [@reload_tasks_id])
|
711
892
|
|
712
|
-
@
|
893
|
+
@oata.events.disconnect(:timelog_active_changed, @event_timelog_active_changed) if @event_timelog_active_changed
|
713
894
|
@event_timelog_active_changed = nil
|
714
895
|
Gtk.timeout_remove(@timeout_id)
|
715
896
|
end
|
716
897
|
|
717
898
|
def on_expOverview_activate(expander)
|
718
899
|
if expander.expanded?
|
719
|
-
|
900
|
+
self.window_resize_height_enable
|
901
|
+
@log.debug("Current window-size: #{@window.size}")
|
902
|
+
size = @window.size
|
903
|
+
@window.resize(size[0], 480) if size[1] < 480
|
720
904
|
self.timelog_info_trigger
|
721
905
|
else
|
722
|
-
|
723
|
-
|
724
|
-
@gui["window"].resize(@gui["window"].size[0], 1)
|
725
|
-
false
|
726
|
-
end
|
906
|
+
self.window_resize_height_disable
|
907
|
+
self.timelog_info_trigger
|
727
908
|
end
|
728
909
|
end
|
729
910
|
|
730
911
|
#This method handles the "Timelog info"-frame. Hides, shows and updates the info in it.
|
731
912
|
def timelog_info_trigger
|
732
|
-
if tlog = @
|
733
|
-
time_tracked = @
|
913
|
+
if tlog = @oata.timelog_active
|
914
|
+
time_tracked = @oata.timelog_active_time_tracked + tlog.time_total
|
734
915
|
@gui["btnSwitch"].label = "#{_("Stop")} (#{Knj::Strings.secs_to_human_short_time(time_tracked)})"
|
735
916
|
|
736
917
|
#Update icon every second while showing main-window, so it looks like stop-button and tray-icon-time is in sync (else tray will only update every 30 sec. which will make it look out of sync, even though it wont be).
|
737
|
-
@
|
918
|
+
@oata.ti.update_icon
|
738
919
|
end
|
739
920
|
end
|
740
921
|
|
741
922
|
def on_btnSwitch_clicked
|
742
|
-
if @
|
743
|
-
@
|
923
|
+
if @oata.timelog_active
|
924
|
+
@oata.timelog_stop_tracking
|
744
925
|
@gui["txtDescr"].grab_focus
|
745
926
|
else
|
746
927
|
descr = @gui["txtDescr"].text.to_s.strip
|
@@ -752,20 +933,20 @@ class Openall_time_applet::Gui::Win_main
|
|
752
933
|
task_id = task.id
|
753
934
|
end
|
754
935
|
|
755
|
-
timelog = @
|
936
|
+
timelog = @ob.get_by(:Timelog, {
|
756
937
|
"task_id" => task_id,
|
757
938
|
"descr_lower" => descr,
|
758
939
|
"timestamp_day" => Time.now
|
759
940
|
})
|
760
941
|
|
761
942
|
if !timelog
|
762
|
-
timelog = @
|
943
|
+
timelog = @ob.add(:Timelog, {
|
763
944
|
:task_id => task_id,
|
764
945
|
:descr => descr
|
765
946
|
})
|
766
947
|
end
|
767
948
|
|
768
|
-
@
|
949
|
+
@oata.timelog_active = timelog
|
769
950
|
@gui["txtDescr"].text = ""
|
770
951
|
@gui["cbTask"].sel = _("Choose:")
|
771
952
|
end
|
@@ -776,7 +957,7 @@ class Openall_time_applet::Gui::Win_main
|
|
776
957
|
#This method updates the switch button to start or stop, based on the if a timelog is tracked or not.
|
777
958
|
def update_switch_button
|
778
959
|
but = @gui["btnSwitch"]
|
779
|
-
tlog_act = @
|
960
|
+
tlog_act = @oata.timelog_active
|
780
961
|
|
781
962
|
if tlog_act
|
782
963
|
but.image = Gtk::Image.new(Gtk::Stock::MEDIA_STOP, Gtk::IconSize::BUTTON)
|
@@ -805,7 +986,7 @@ class Openall_time_applet::Gui::Win_main
|
|
805
986
|
#This method runs through all rows in the treeview and checks if a row should be marked with bold. It also increases the time in the time-column for the tracked timelog.
|
806
987
|
def check_rows
|
807
988
|
return nil if @tv_editting
|
808
|
-
act_timelog = @
|
989
|
+
act_timelog = @oata.timelog_active
|
809
990
|
|
810
991
|
if act_timelog
|
811
992
|
act_timelog_id = act_timelog.id
|
@@ -813,40 +994,59 @@ class Openall_time_applet::Gui::Win_main
|
|
813
994
|
act_timelog_id = nil
|
814
995
|
end
|
815
996
|
|
816
|
-
|
997
|
+
col_no_track = @tv_settings.col_orig_no_for_id(:track)
|
817
998
|
|
818
|
-
@
|
999
|
+
@tv.model.each do |model, path, iter|
|
819
1000
|
timelog_id = model.get_value(iter, 0).to_i
|
820
1001
|
bold = false
|
821
|
-
iter_id = iter.to_s.to_i
|
822
1002
|
|
823
1003
|
#Update time tracked.
|
824
1004
|
if timelog_id == act_timelog_id
|
825
|
-
secs = act_timelog.time_total + @
|
1005
|
+
secs = act_timelog.time_total + @oata.timelog_active_time_tracked
|
826
1006
|
col_no = @tv_settings.col_orig_no_for_id(:time)
|
827
1007
|
iter[col_no] = "<b>#{Knj::Strings.secs_to_human_time_str(secs, :secs => false)}</b>"
|
828
1008
|
bold = true
|
1009
|
+
|
1010
|
+
@log.debug("Setting track-check for timelog '#{timelog_id}'.")
|
1011
|
+
iter[col_no_track] = 1
|
1012
|
+
else
|
1013
|
+
if iter[col_no_track] == 1
|
1014
|
+
#Track-check-value is set for a timelog that isnt being tracked - remove it.
|
1015
|
+
@log.debug("Remove track-check for timelog '#{timelog_id}'.")
|
1016
|
+
iter[col_no_track] = 0
|
1017
|
+
end
|
1018
|
+
|
1019
|
+
if @bold_rows[timelog_id] == true
|
1020
|
+
#Remove bold text if timelog is not being tracked.
|
1021
|
+
ROWS_BOLD.each do |row_no|
|
1022
|
+
col_no = @tv_settings.col_orig_no_for_id(row_no)
|
1023
|
+
cur_val = model.get_value(iter, col_no)
|
1024
|
+
iter[col_no] = cur_val.gsub(/^<b>/i, "").gsub(/<\/b>$/i, "")
|
1025
|
+
end
|
1026
|
+
|
1027
|
+
@bold_rows.delete(timelog_id)
|
1028
|
+
end
|
829
1029
|
end
|
830
1030
|
|
831
1031
|
#Set all columns to bold if not already set.
|
832
|
-
if bold and !@bold_rows.key?(
|
833
|
-
|
1032
|
+
if bold and !@bold_rows.key?(timelog_id)
|
1033
|
+
ROWS_BOLD.each do |row_no|
|
834
1034
|
col_no = @tv_settings.col_orig_no_for_id(row_no)
|
835
1035
|
iter[col_no] = "<b>#{model.get_value(iter, col_no)}</b>"
|
836
1036
|
end
|
837
1037
|
|
838
|
-
@bold_rows[
|
1038
|
+
@bold_rows[timelog_id] = true
|
839
1039
|
end
|
840
1040
|
end
|
841
1041
|
end
|
842
1042
|
|
843
1043
|
def on_miSyncStatic_activate
|
844
|
-
@
|
1044
|
+
@oata.sync_static("transient_for" => @window)
|
845
1045
|
end
|
846
1046
|
|
847
1047
|
def on_btnMinus_clicked
|
848
|
-
sel = @
|
849
|
-
tlog = @
|
1048
|
+
sel = @tv.sel
|
1049
|
+
tlog = @ob.get(:Timelog, sel[0]) if sel
|
850
1050
|
|
851
1051
|
if !sel or !tlog
|
852
1052
|
Knj::Gtk2.msgbox(_("Please choose a timelog to delete."), "warning")
|
@@ -855,7 +1055,8 @@ class Openall_time_applet::Gui::Win_main
|
|
855
1055
|
|
856
1056
|
return nil if Knj::Gtk2.msgbox(_("Do you want to remove this timelog?"), "yesno") != "yes"
|
857
1057
|
begin
|
858
|
-
@
|
1058
|
+
@log.debug("Deleting timelog from pressing minus and confirming: '#{tlog.id}'.")
|
1059
|
+
@ob.delete(tlog)
|
859
1060
|
rescue => e
|
860
1061
|
Knj::Gtk2.msgbox(sprintf(_("Could not delete the timelog: %s"), e.message))
|
861
1062
|
end
|
@@ -863,18 +1064,20 @@ class Openall_time_applet::Gui::Win_main
|
|
863
1064
|
|
864
1065
|
def on_btnPlus_clicked
|
865
1066
|
#Add new timelog to database.
|
866
|
-
timelog = @
|
1067
|
+
timelog = @ob.add(:Timelog)
|
1068
|
+
@log.debug("Timelog added from pressing plus-button: '#{timelog.to_hash}'.")
|
867
1069
|
|
868
1070
|
#Focus new timelog in treeview and open the in-line-editting for the description.
|
869
1071
|
added_id = timelog.id.to_i
|
870
1072
|
|
871
|
-
@
|
1073
|
+
@tv.model.each do |model, path, iter|
|
872
1074
|
col_no = @tv_settings.col_no_for_id(:id)
|
873
1075
|
timelog_id = model.get_value(iter, col_no).to_i
|
874
1076
|
|
875
1077
|
if timelog_id == added_id
|
876
|
-
|
877
|
-
@
|
1078
|
+
@log.debug("Setting focus to added timelog.")
|
1079
|
+
col = @tv.columns[1]
|
1080
|
+
@tv.set_cursor(path, col, true)
|
878
1081
|
break
|
879
1082
|
end
|
880
1083
|
end
|
@@ -888,10 +1091,21 @@ class Openall_time_applet::Gui::Win_main
|
|
888
1091
|
def on_btnSyncPrepareTransfer_clicked
|
889
1092
|
begin
|
890
1093
|
#Destroy this window and start syncing for real.
|
891
|
-
@
|
892
|
-
@
|
1094
|
+
@window.destroy
|
1095
|
+
@oata.sync_real
|
893
1096
|
rescue => e
|
894
1097
|
Knj::Gtk2.msgbox(Knj::Errors.error_str(e))
|
895
1098
|
end
|
896
1099
|
end
|
1100
|
+
|
1101
|
+
#Enables or disables the minus-button based on what is selected in the treeview.
|
1102
|
+
def validate_minus_active(*args)
|
1103
|
+
sel = @tv.sel
|
1104
|
+
|
1105
|
+
if sel and sel[0].to_i > 0
|
1106
|
+
@gui["btnMinus"].sensitive = true
|
1107
|
+
else
|
1108
|
+
@gui["btnMinus"].sensitive = false
|
1109
|
+
end
|
1110
|
+
end
|
897
1111
|
end
|