openall_time_applet 0.0.37 → 0.0.38
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/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"
|