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 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"