openall_time_applet 0.0.37 → 0.0.38
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/bin/OpenAll Timelogging +1 -1
- data/bin/openall_time_applet.rb +1 -1
- data/gui/trayicon.rb +2 -0
- data/gui/win_main.rb +232 -103
- data/lib/openall_time_applet.rb +1 -2
- data/openall_time_applet.gemspec +2 -2
- metadata +3 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.38
|
data/bin/OpenAll Timelogging
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
Dir.chdir(File.dirname(__FILE__))
|
6
6
|
require "../lib/openall_time_applet.rb"
|
7
7
|
|
8
|
-
GetText.bindtextdomain("default", "../locales",
|
8
|
+
GetText.bindtextdomain("default", "../locales", Knj::Locales.lang["full"])
|
9
9
|
|
10
10
|
oata = Openall_time_applet.new(:debug => true)
|
11
11
|
|
data/bin/openall_time_applet.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
Dir.chdir(File.dirname(__FILE__))
|
4
4
|
require "../lib/openall_time_applet.rb"
|
5
5
|
|
6
|
-
GetText.bindtextdomain("default", "../locales",
|
6
|
+
GetText.bindtextdomain("default", "../locales", Knj::Locales.lang["full"])
|
7
7
|
|
8
8
|
oata = Openall_time_applet.new(:debug => true)
|
9
9
|
|
data/gui/trayicon.rb
CHANGED
@@ -8,6 +8,8 @@ class Openall_time_applet::Gui::Trayicon
|
|
8
8
|
@mutex_update_icon = Mutex.new
|
9
9
|
|
10
10
|
@ti = Gtk::StatusIcon.new
|
11
|
+
@ti.icon_name = "OpenAll Timelogging"
|
12
|
+
@ti.tooltip = "OpenAll Timelogging"
|
11
13
|
@ti.signal_connect("popup-menu", &self.method(:on_statusicon_rightclick))
|
12
14
|
@ti.signal_connect("activate", &self.method(:on_statusicon_leftclick))
|
13
15
|
self.update_icon
|
data/gui/win_main.rb
CHANGED
@@ -38,70 +38,78 @@ class Openall_time_applet::Gui::Win_main
|
|
38
38
|
#Add the tasks to the combo-box.
|
39
39
|
@gui["cbTask"].init(tasks)
|
40
40
|
|
41
|
-
init_data = @gui["tvTimelogs"].init(
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
41
|
+
init_data = @gui["tvTimelogs"].init(
|
42
|
+
:type => :treestore,
|
43
|
+
:cols => [
|
44
|
+
_("ID"),
|
45
|
+
{
|
46
|
+
:title => _("Stamp"),
|
47
|
+
:type => :string,
|
48
|
+
:markup => true,
|
49
|
+
:expand => false
|
50
|
+
},
|
51
|
+
{
|
52
|
+
:title => _("Time"),
|
53
|
+
:type => :string,
|
54
|
+
:markup => true,
|
55
|
+
:expand => false
|
56
|
+
},
|
57
|
+
{
|
58
|
+
:title => _("Description"),
|
59
|
+
:type => :string,
|
60
|
+
:markup => true,
|
61
|
+
:expand => true,
|
62
|
+
:fixed_width => 160
|
63
|
+
},
|
64
|
+
{
|
65
|
+
:title => _("T-time"),
|
66
|
+
:type => :string,
|
67
|
+
:markup => true,
|
68
|
+
:expand => false
|
69
|
+
},
|
70
|
+
{
|
71
|
+
:title => _("T-km"),
|
72
|
+
:type => :string,
|
73
|
+
:markup => true
|
74
|
+
},
|
75
|
+
{
|
76
|
+
:title => _("T-Descr."),
|
77
|
+
:type => :string,
|
78
|
+
:markup => true,
|
79
|
+
:expand => true,
|
80
|
+
:fixed_width => 160
|
81
|
+
},
|
82
|
+
{
|
83
|
+
:title => _("Cost"),
|
84
|
+
:type => :string,
|
85
|
+
:markup => true
|
86
|
+
},
|
87
|
+
{
|
88
|
+
:title => _("Fixed"),
|
89
|
+
:type => :toggle,
|
90
|
+
:expand => false
|
91
|
+
},
|
92
|
+
{
|
93
|
+
:title => _("Work"),
|
94
|
+
:type => :toggle,
|
95
|
+
:expand => false
|
96
|
+
},
|
97
|
+
{
|
98
|
+
:title => _("Task"),
|
99
|
+
:type => :combo,
|
100
|
+
:model => task_ls,
|
101
|
+
:has_entry => false,
|
102
|
+
:markup => true,
|
103
|
+
:expand => true,
|
104
|
+
:fixed_width => 160
|
105
|
+
},
|
106
|
+
{
|
107
|
+
:title => _("Track"),
|
108
|
+
:type => :toggle,
|
109
|
+
:expand => false
|
110
|
+
}
|
111
|
+
]
|
112
|
+
)
|
105
113
|
|
106
114
|
@tv_settings = Gtk2_treeview_settings.new(
|
107
115
|
:id => "win_main_tvTimelogs",
|
@@ -117,7 +125,8 @@ class Openall_time_applet::Gui::Win_main
|
|
117
125
|
7 => :cost,
|
118
126
|
8 => :fixed,
|
119
127
|
9 => :int,
|
120
|
-
10 => :task
|
128
|
+
10 => :task,
|
129
|
+
11 => :track
|
121
130
|
}
|
122
131
|
)
|
123
132
|
|
@@ -176,6 +185,22 @@ class Openall_time_applet::Gui::Win_main
|
|
176
185
|
end
|
177
186
|
},
|
178
187
|
:value_set_callback => proc{|data| data[:model].task_name }
|
188
|
+
},
|
189
|
+
11 => {
|
190
|
+
:value_callback => lambda{|data|
|
191
|
+
if !data[:model]
|
192
|
+
Knj::Gtk2.msgbox(_("You cannot track a date. Please track a timelog instead."))
|
193
|
+
return false
|
194
|
+
else
|
195
|
+
if data[:value]
|
196
|
+
@args[:oata].timelog_active = data[:model]
|
197
|
+
elsif data[:model] == @args[:oata].timelog_active
|
198
|
+
@args[:oata].timelog_stop_tracking
|
199
|
+
end
|
200
|
+
|
201
|
+
return data[:model] == @args[:oata].timelog_active
|
202
|
+
end
|
203
|
+
}
|
179
204
|
}
|
180
205
|
}
|
181
206
|
)
|
@@ -199,6 +224,7 @@ class Openall_time_applet::Gui::Win_main
|
|
199
224
|
|
200
225
|
#Reload the treeview if something happened to a timelog.
|
201
226
|
@reload_id = @args[:oata].ob.connect("object" => :Timelog, "signals" => ["add", "update", "delete"], &self.method(:reload_timelogs))
|
227
|
+
@reload_id_update = @args[:oata].ob.connect("object" => :Timelog, "signals" => ["update"], &self.method(:on_timelog_update))
|
202
228
|
|
203
229
|
|
204
230
|
#Update switch-button.
|
@@ -348,31 +374,19 @@ class Openall_time_applet::Gui::Win_main
|
|
348
374
|
return true
|
349
375
|
end
|
350
376
|
|
377
|
+
#This is called when updating a timelogs timestamp through the treeview.
|
351
378
|
def tv_editable_timestamp_callback(data)
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
return
|
357
|
-
elsif match = data[:value].match(/^\s*(\d+)\s*\/\s*(\d+)\s*$/)
|
358
|
-
date = data[:model].timestamp
|
359
|
-
date.day = match[1].to_i
|
360
|
-
date.month = match[2].to_i
|
361
|
-
|
362
|
-
return date
|
363
|
-
else
|
364
|
-
return Datet.in(data[:value])
|
379
|
+
begin
|
380
|
+
return data[:model].timestamp.update_from_str(data[:value])
|
381
|
+
rescue => e
|
382
|
+
Knj::Gtk2.msgbox(e.message)
|
383
|
+
return data[:model].timestamp
|
365
384
|
end
|
366
385
|
end
|
367
386
|
|
387
|
+
#This is called when a timelogs timestamp should be shown.
|
368
388
|
def tv_editable_timestamp_set_callback(data)
|
369
|
-
|
370
|
-
|
371
|
-
if date.strftime("%Y %m %d") == Time.now.strftime("%Y %m %d")
|
372
|
-
return date.strftime("%H:%M")
|
373
|
-
else
|
374
|
-
return date.strftime("%d/%m")
|
375
|
-
end
|
389
|
+
return Datet.in(data[:value]).strftime("%H:%M")
|
376
390
|
end
|
377
391
|
|
378
392
|
#Reloads the suggestions for the description-entry-completion.
|
@@ -510,8 +524,36 @@ class Openall_time_applet::Gui::Win_main
|
|
510
524
|
|
511
525
|
return nil if @dont_reload or @gui["tvTimelogs"].destroyed?
|
512
526
|
tnow_str = Time.now.strftime("%Y %m %d")
|
513
|
-
|
514
527
|
@gui["tvTimelogs"].model.clear
|
528
|
+
|
529
|
+
#Create date-parent elements that the timelogs will be appended under.
|
530
|
+
dates = {}
|
531
|
+
now_year = Time.now.year
|
532
|
+
|
533
|
+
@args[:oata].ob.list(:Timelog, "orderby" => "timestamp") do |tlog|
|
534
|
+
tstamp = Datet.in(tlog[:timestamp])
|
535
|
+
str = tstamp.out(:time => false)
|
536
|
+
|
537
|
+
if !dates.key?(str)
|
538
|
+
tstamp_year = tstamp.year
|
539
|
+
|
540
|
+
if tstamp_year != now_year
|
541
|
+
date_str = str
|
542
|
+
else
|
543
|
+
date_str = tstamp.out(:time => false, :year => false)
|
544
|
+
end
|
545
|
+
|
546
|
+
iter = @tv_settings.tv.model.append(nil)
|
547
|
+
iter[1] = "<b>#{Knj::Web.html(date_str)}</b>"
|
548
|
+
|
549
|
+
dates[str] = {
|
550
|
+
:iter => iter,
|
551
|
+
:tlogs => []
|
552
|
+
}
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
#Append the timelogs to the parent dates.
|
515
557
|
@args[:oata].ob.list(:Timelog, "orderby" => ["task_id", "descr", "timestamp"]) do |timelog|
|
516
558
|
begin
|
517
559
|
tstamp_str = timelog.timestamp_str
|
@@ -520,32 +562,118 @@ class Openall_time_applet::Gui::Win_main
|
|
520
562
|
end
|
521
563
|
|
522
564
|
tstamp = timelog.timestamp
|
565
|
+
tstamp_str = tstamp.strftime("%H:%M")
|
523
566
|
|
524
|
-
|
525
|
-
tstamp_str = tstamp.strftime("%H:%M")
|
526
|
-
else
|
527
|
-
tstamp_str = tstamp.strftime("%d/%m")
|
528
|
-
end
|
567
|
+
parent = dates[tstamp.out(:time => false)][:iter]
|
529
568
|
|
530
|
-
@tv_settings.
|
531
|
-
:
|
532
|
-
:
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
569
|
+
@tv_settings.append_adv(
|
570
|
+
:parent => parent,
|
571
|
+
:data => {
|
572
|
+
:id => timelog.id,
|
573
|
+
:timestamp => tstamp_str,
|
574
|
+
:time => timelog.time_as_human,
|
575
|
+
:descr => Knj::Web.html(timelog[:descr]),
|
576
|
+
:ttime => timelog.time_transport_as_human,
|
577
|
+
:tkm => Knj::Locales.number_out(timelog[:transportlength], 0),
|
578
|
+
:tdescr => Knj::Web.html(timelog[:transportdescription]),
|
579
|
+
:cost => Knj::Locales.number_out(timelog[:transportcosts], 2),
|
580
|
+
:fixed => Knj::Strings.yn_str(timelog[:travelfixed], true, false),
|
581
|
+
:int => Knj::Strings.yn_str(timelog[:workinternal], true, false),
|
582
|
+
:task => timelog.task_name
|
583
|
+
}
|
542
584
|
)
|
543
585
|
end
|
544
586
|
|
587
|
+
#Make all dates expand their content (timelogs).
|
588
|
+
@gui["tvTimelogs"].expand_all
|
589
|
+
|
545
590
|
#Reset cache of which rows are set to bold.
|
546
591
|
@bold_rows = {}
|
547
592
|
end
|
548
593
|
|
594
|
+
def timelog_tv_data_by_timelog(timelog)
|
595
|
+
@gui["tvTimelogs"].model.each do |model, path, iter|
|
596
|
+
timelog_i_id = iter[0].to_i
|
597
|
+
|
598
|
+
if timelog.id.to_i == timelog_i_id
|
599
|
+
return {
|
600
|
+
:timelog => timelog,
|
601
|
+
:iter => iter,
|
602
|
+
:path => path
|
603
|
+
}
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
607
|
+
raise sprintf(_("Could not find timelog in treeview: '%s'."), timelog.id)
|
608
|
+
end
|
609
|
+
|
610
|
+
def date_tv_data_by_datet(datet, args = nil)
|
611
|
+
datet_str = datet.out(:time => false)
|
612
|
+
add_after = nil
|
613
|
+
|
614
|
+
@gui["tvTimelogs"].model.each do |model, path, iter|
|
615
|
+
#Skip the iter's that are timelogs (we look for a parent-date).
|
616
|
+
timelog_id = iter[0].to_i
|
617
|
+
next if timelog_id != 0
|
618
|
+
|
619
|
+
date_i_str = Php4r.strip_tags(iter[1])
|
620
|
+
|
621
|
+
if date_i_str == datet_str
|
622
|
+
return {
|
623
|
+
:iter => iter,
|
624
|
+
:path => path
|
625
|
+
}
|
626
|
+
end
|
627
|
+
|
628
|
+
datet_i = Datet.in(date_i_str)
|
629
|
+
|
630
|
+
if datet_i < datet
|
631
|
+
add_after = iter
|
632
|
+
end
|
633
|
+
end
|
634
|
+
|
635
|
+
if args and args[:add]
|
636
|
+
iter = @gui["tvTimelogs"].insert_after(nil, add_after)
|
637
|
+
iter[1] = "<b>#{Knj::Web.html(datet.out(:time => false))}</b>"
|
638
|
+
|
639
|
+
return {
|
640
|
+
:iter => iter
|
641
|
+
}
|
642
|
+
end
|
643
|
+
|
644
|
+
raise sprintf(_("Could not find iter from that date: '%s'."), datet)
|
645
|
+
end
|
646
|
+
|
647
|
+
#This method is called every time a timelog is updated (changed). This is needed to move timelogs around under the right dates, when the date is changed for a timelog.
|
648
|
+
def on_timelog_update(timelog)
|
649
|
+
#Get the treeview-data for the selected timelog.
|
650
|
+
tlog_data = self.timelog_tv_data_by_timelog(timelog)
|
651
|
+
|
652
|
+
#Get the date from the parent treeview-iter.
|
653
|
+
parent_iter = tlog_data[:iter].parent
|
654
|
+
parent_date = Php4r.strip_tags(parent_iter[1])
|
655
|
+
|
656
|
+
#Get the date from the selected timelog.
|
657
|
+
tlog_date_str = timelog.timestamp.out(:time => false)
|
658
|
+
|
659
|
+
#The date of the timelog has been updated, and the timelog has to be moved elsewhere in the treeview.
|
660
|
+
if parent_date != tlog_date_str
|
661
|
+
#Wait 5 miliseconds so the 'dont_reload' variable wont be 'true' any more.
|
662
|
+
Gtk.timeout_add(5) do
|
663
|
+
#Reload timelogs to make the changed timelog appear under the right date.
|
664
|
+
self.reload_timelogs
|
665
|
+
|
666
|
+
#Re-select the timelog in the treeview.
|
667
|
+
tlog_data = self.timelog_tv_data_by_timelog(timelog)
|
668
|
+
@gui["tvTimelogs"].selection.select_iter(tlog_data[:iter])
|
669
|
+
|
670
|
+
#Return false for the timeout, so it wont be called again.
|
671
|
+
false
|
672
|
+
end
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
#Called when the quit-menu-item is activated.
|
549
677
|
def on_imiQuit_activate
|
550
678
|
#Check if a timelog needs to be synced. If so the user needs to confirm he really wants to quit.
|
551
679
|
timelog_found = nil
|
@@ -578,6 +706,7 @@ class Openall_time_applet::Gui::Win_main
|
|
578
706
|
def on_window_destroy
|
579
707
|
#Unconnect reload-event. Else it will crash on call to destroyed object. Also frees up various ressources.
|
580
708
|
@args[:oata].ob.unconnect("object" => :Timelog, "conn_id" => @reload_id)
|
709
|
+
@args[:oata].ob.unconnect("object" => :Timelog, "conn_id" => @reload_id_update)
|
581
710
|
@args[:oata].ob.unconnect("object" => :Timelog, "conn_id" => @reload_preparetransfer_id)
|
582
711
|
|
583
712
|
@args[:oata].events.disconnect(:timelog_active_changed, @event_timelog_active_changed) if @event_timelog_active_changed
|
data/lib/openall_time_applet.rb
CHANGED
@@ -14,7 +14,6 @@ gems.each do |gem|
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
17
|
require "sqlite3"
|
19
18
|
require "gettext"
|
20
19
|
require "base64"
|
@@ -23,7 +22,7 @@ require "base64"
|
|
23
22
|
class Openall_time_applet
|
24
23
|
#Shortcut to start the application. Used by the Ubuntu-package.
|
25
24
|
def self.exec
|
26
|
-
require "#{File.dirname(__FILE__)}/../bin/openall_time_applet"
|
25
|
+
require "#{File.dirname(__FILE__)}/../bin/openall_time_applet.rb"
|
27
26
|
end
|
28
27
|
|
29
28
|
#Subclass controlling autoloading of models.
|
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.38"
|
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-08-
|
12
|
+
s.date = %q{2012-08-23}
|
13
13
|
s.description = %q{Off-line time-tracking for OpenAll with syncing when online.}
|
14
14
|
s.email = %q{k@spernj.org}
|
15
15
|
s.executables = ["OpenAll Timelogging", "openall_time_applet.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.38
|
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-08-
|
13
|
+
date: 2012-08-23 00:00:00 +02:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -220,7 +220,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
220
220
|
requirements:
|
221
221
|
- - ">="
|
222
222
|
- !ruby/object:Gem::Version
|
223
|
-
hash:
|
223
|
+
hash: 1563791381235763168
|
224
224
|
segments:
|
225
225
|
- 0
|
226
226
|
version: "0"
|