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 CHANGED
@@ -1 +1 @@
1
- 0.0.37
1
+ 0.0.38
@@ -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", ENV["LANGUAGE"])
8
+ GetText.bindtextdomain("default", "../locales", Knj::Locales.lang["full"])
9
9
 
10
10
  oata = Openall_time_applet.new(:debug => true)
11
11
 
@@ -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", ENV["LANGUAGE"])
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
- _("ID"),
43
- {
44
- :title => _("Stamp"),
45
- :type => :string,
46
- :markup => true,
47
- :expand => false
48
- },
49
- {
50
- :title => _("Time"),
51
- :type => :string,
52
- :markup => true,
53
- :expand => false
54
- },
55
- {
56
- :title => _("Description"),
57
- :type => :string,
58
- :markup => true,
59
- :expand => true,
60
- :fixed_width => 160
61
- },
62
- {
63
- :title => _("T-time"),
64
- :type => :string,
65
- :markup => true,
66
- :expand => false
67
- },
68
- {
69
- :title => _("T-km"),
70
- :type => :string,
71
- :markup => true
72
- },
73
- {
74
- :title => _("T-Descr."),
75
- :type => :string,
76
- :markup => true,
77
- :expand => true,
78
- :fixed_width => 160
79
- },
80
- {
81
- :title => _("Cost"),
82
- :type => :string,
83
- :markup => true
84
- },
85
- {
86
- :title => _("Fixed"),
87
- :type => :toggle,
88
- :expand => false
89
- },
90
- {
91
- :title => _("Work"),
92
- :type => :toggle,
93
- :expand => false
94
- },
95
- {
96
- :title => _("Task"),
97
- :type => :combo,
98
- :model => task_ls,
99
- :has_entry => false,
100
- :markup => true,
101
- :expand => true,
102
- :fixed_width => 160
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
- if match = data[:value].match(/^\s*(\d+)\s*:\s*(\d+)\s*$/)
353
- date = Datet.new
354
- date.hour = match[1].to_i
355
- date.min = match[2].to_i
356
- return date
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
- date = Datet.in(data[:value])
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
- if tstamp.strftime("%Y %m %d") == tnow_str
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.append(
531
- :id => timelog.id,
532
- :timestamp => tstamp_str,
533
- :time => timelog.time_as_human,
534
- :descr => Knj::Web.html(timelog[:descr]),
535
- :ttime => timelog.time_transport_as_human,
536
- :tkm => Knj::Locales.number_out(timelog[:transportlength], 0),
537
- :tdescr => Knj::Web.html(timelog[:transportdescription]),
538
- :cost => Knj::Locales.number_out(timelog[:transportcosts], 2),
539
- :fixed => Knj::Strings.yn_str(timelog[:travelfixed], true, false),
540
- :int => Knj::Strings.yn_str(timelog[:workinternal], true, false),
541
- :task => timelog.task_name
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
@@ -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.
@@ -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.37"
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-20}
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.37
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-20 00:00:00 +02:00
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: -2640804252727998284
223
+ hash: 1563791381235763168
224
224
  segments:
225
225
  - 0
226
226
  version: "0"