openall_time_applet 0.0.14 → 0.0.15
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/conf/db_schema.rb +12 -0
- data/glade/win_main.glade +1 -0
- data/glade/win_sync_overview.glade +21 -39
- data/gui/win_main.rb +1 -11
- data/gui/win_sync_overview.rb +158 -32
- data/lib/openall_time_applet.rb +30 -18
- data/models/timelog.rb +5 -1
- data/models/timelog_logged_time.rb +9 -0
- data/openall_time_applet.gemspec +3 -5
- metadata +4 -6
- data/glade/win_timelog_edit.glade +0 -440
- data/gui/win_overview.rb +0 -5
- data/gui/win_timelog_edit.rb +0 -153
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.15
|
data/conf/db_schema.rb
CHANGED
@@ -35,6 +35,7 @@ Openall_time_applet::DB_SCHEMA = {
|
|
35
35
|
{"name" => "task_id", "type" => "int"},
|
36
36
|
{"name" => "timestamp", "type" => "datetime"},
|
37
37
|
{"name" => "time", "type" => "int"},
|
38
|
+
{"name" => "time_sync", "type" => "varchar"},
|
38
39
|
{"name" => "timetype", "type" => "enum", "maxlength" => "'normal','overtime150','overtime200'", "default" => "normal"},
|
39
40
|
{"name" => "time_transport", "type" => "int"},
|
40
41
|
{"name" => "transportlength", "type" => "int"},
|
@@ -50,6 +51,17 @@ Openall_time_applet::DB_SCHEMA = {
|
|
50
51
|
"task_id"
|
51
52
|
]
|
52
53
|
},
|
54
|
+
"Timelog_logged_time" => {
|
55
|
+
"columns" => [
|
56
|
+
{"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
|
57
|
+
{"name" => "timelog_id", "type" => "int"},
|
58
|
+
{"name" => "timestamp_start", "type" => "datetime"},
|
59
|
+
{"name" => "timestamp_end", "type" => "datetime"}
|
60
|
+
],
|
61
|
+
"indexes" => [
|
62
|
+
"timelog_id"
|
63
|
+
]
|
64
|
+
},
|
53
65
|
"Worktime" => {
|
54
66
|
"columns" => [
|
55
67
|
{"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
|
data/glade/win_main.glade
CHANGED
@@ -14,6 +14,7 @@
|
|
14
14
|
</object>
|
15
15
|
<object class="GtkWindow" id="window">
|
16
16
|
<property name="can_focus">False</property>
|
17
|
+
<property name="title" translatable="yes">OpenAll Time Applet</property>
|
17
18
|
<property name="window_position">center</property>
|
18
19
|
<property name="default_width">640</property>
|
19
20
|
<signal name="destroy" handler="on_window_destroy" swapped="no"/>
|
@@ -6,7 +6,9 @@
|
|
6
6
|
<property name="can_focus">False</property>
|
7
7
|
<property name="title" translatable="yes">Overview of sync</property>
|
8
8
|
<property name="window_position">center</property>
|
9
|
-
<property name="default_width">
|
9
|
+
<property name="default_width">850</property>
|
10
|
+
<property name="default_height">480</property>
|
11
|
+
<signal name="destroy" handler="on_window_destroy" swapped="no"/>
|
10
12
|
<child>
|
11
13
|
<object class="GtkVBox" id="vbox1">
|
12
14
|
<property name="visible">True</property>
|
@@ -28,44 +30,22 @@
|
|
28
30
|
<property name="can_focus">False</property>
|
29
31
|
<property name="spacing">3</property>
|
30
32
|
<child>
|
31
|
-
<object class="
|
33
|
+
<object class="GtkViewport" id="viewport1">
|
32
34
|
<property name="visible">True</property>
|
33
35
|
<property name="can_focus">False</property>
|
34
|
-
<property name="n_columns">3</property>
|
35
36
|
<child>
|
36
|
-
<object class="
|
37
|
+
<object class="GtkScrolledWindow" id="scrolledwindow1">
|
37
38
|
<property name="visible">True</property>
|
38
|
-
<property name="can_focus">
|
39
|
-
<property name="
|
40
|
-
<property name="
|
41
|
-
<
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
<property name="can_focus">False</property>
|
48
|
-
<property name="xalign">0</property>
|
49
|
-
<property name="label" translatable="yes"><b>Logged time</b></property>
|
50
|
-
<property name="use_markup">True</property>
|
51
|
-
</object>
|
52
|
-
<packing>
|
53
|
-
<property name="left_attach">1</property>
|
54
|
-
<property name="right_attach">2</property>
|
55
|
-
</packing>
|
56
|
-
</child>
|
57
|
-
<child>
|
58
|
-
<object class="GtkLabel" id="label5">
|
59
|
-
<property name="visible">True</property>
|
60
|
-
<property name="can_focus">False</property>
|
61
|
-
<property name="xalign">0</property>
|
62
|
-
<property name="label" translatable="yes"><b>Sync. as time</b></property>
|
63
|
-
<property name="use_markup">True</property>
|
39
|
+
<property name="can_focus">True</property>
|
40
|
+
<property name="hscrollbar_policy">automatic</property>
|
41
|
+
<property name="vscrollbar_policy">automatic</property>
|
42
|
+
<child>
|
43
|
+
<object class="GtkTreeView" id="tvTimelogs">
|
44
|
+
<property name="visible">True</property>
|
45
|
+
<property name="can_focus">True</property>
|
46
|
+
</object>
|
47
|
+
</child>
|
64
48
|
</object>
|
65
|
-
<packing>
|
66
|
-
<property name="left_attach">2</property>
|
67
|
-
<property name="right_attach">3</property>
|
68
|
-
</packing>
|
69
49
|
</child>
|
70
50
|
</object>
|
71
51
|
<packing>
|
@@ -98,7 +78,7 @@
|
|
98
78
|
</child>
|
99
79
|
</object>
|
100
80
|
<packing>
|
101
|
-
<property name="expand">
|
81
|
+
<property name="expand">False</property>
|
102
82
|
<property name="fill">True</property>
|
103
83
|
<property name="position">1</property>
|
104
84
|
</packing>
|
@@ -111,24 +91,26 @@
|
|
111
91
|
<object class="GtkLabel" id="label2">
|
112
92
|
<property name="visible">True</property>
|
113
93
|
<property name="can_focus">False</property>
|
114
|
-
<property name="label" translatable="yes"><b>
|
94
|
+
<property name="label" translatable="yes"><b>Prepare synchronization</b></property>
|
115
95
|
<property name="use_markup">True</property>
|
116
96
|
</object>
|
117
97
|
</child>
|
118
98
|
</object>
|
119
99
|
<packing>
|
120
|
-
<property name="expand">
|
100
|
+
<property name="expand">True</property>
|
121
101
|
<property name="fill">True</property>
|
122
102
|
<property name="position">0</property>
|
123
103
|
</packing>
|
124
104
|
</child>
|
125
105
|
<child>
|
126
|
-
<object class="GtkLabel" id="
|
106
|
+
<object class="GtkLabel" id="labTotal">
|
127
107
|
<property name="visible">True</property>
|
128
108
|
<property name="can_focus">False</property>
|
109
|
+
<property name="xalign">0</property>
|
110
|
+
<property name="label" translatable="yes">[totals]</property>
|
129
111
|
</object>
|
130
112
|
<packing>
|
131
|
-
<property name="expand">
|
113
|
+
<property name="expand">False</property>
|
132
114
|
<property name="fill">True</property>
|
133
115
|
<property name="position">1</property>
|
134
116
|
</packing>
|
data/gui/win_main.rb
CHANGED
@@ -128,16 +128,6 @@ class Openall_time_applet::Gui::Win_main
|
|
128
128
|
end
|
129
129
|
end
|
130
130
|
|
131
|
-
def on_tvTimelogs_row_activated(*args)
|
132
|
-
row = @gui["tvTimelogs"].sel
|
133
|
-
return nil if !row
|
134
|
-
|
135
|
-
timelog = @args[:oata].ob.get(:Timelog, row[0])
|
136
|
-
win_timelog_edit = @args[:oata].show_timelog_edit(timelog)
|
137
|
-
win_timelog_edit.gui["window"].modal = @gui["window"]
|
138
|
-
win_timelog_edit.gui["window"].transient_for = @gui["window"]
|
139
|
-
end
|
140
|
-
|
141
131
|
def on_imiQuit_activate
|
142
132
|
@gui["window"].destroy
|
143
133
|
end
|
@@ -180,7 +170,7 @@ class Openall_time_applet::Gui::Win_main
|
|
180
170
|
end
|
181
171
|
|
182
172
|
def on_btnSync_clicked
|
183
|
-
@args[:oata].sync_static do
|
173
|
+
@args[:oata].sync_static("transient_for" => @gui["window"]) do
|
184
174
|
@args[:oata].sync
|
185
175
|
end
|
186
176
|
end
|
data/gui/win_sync_overview.rb
CHANGED
@@ -6,30 +6,95 @@ class Openall_time_applet::Gui::Win_sync_overview
|
|
6
6
|
@gui = Gtk::Builder.new.add("../glade/win_sync_overview.glade")
|
7
7
|
@gui.translate
|
8
8
|
@gui.connect_signals{|h|method(h)}
|
9
|
-
@gui["btnSync"].label = _("
|
9
|
+
@gui["btnSync"].label = _("Transfer")
|
10
10
|
|
11
|
-
#
|
12
|
-
|
11
|
+
#Generate list-store containing tasks for the task-column.
|
12
|
+
task_ls = Gtk::ListStore.new(String, String)
|
13
|
+
iter = task_ls.append
|
14
|
+
iter[0] = _("None")
|
15
|
+
iter[1] = 0.to_s
|
13
16
|
|
17
|
+
tasks = [_("Choose:")]
|
18
|
+
@args[:oata].ob.list(:Task, {"orderby" => "title"}) do |task|
|
19
|
+
iter = task_ls.append
|
20
|
+
iter[0] = task[:title]
|
21
|
+
iter[1] = task.id.to_s
|
22
|
+
tasks << task
|
23
|
+
end
|
24
|
+
|
25
|
+
#Initialize timelog treeview.
|
26
|
+
init_data = Knj::Gtk2::Tv.init(@gui["tvTimelogs"], [
|
27
|
+
_("ID"),
|
28
|
+
_("Description"),
|
29
|
+
_("Timestamp"),
|
30
|
+
_("Time"),
|
31
|
+
_("Transport"),
|
32
|
+
_("Length"),
|
33
|
+
_("Transport descr."),
|
34
|
+
_("Transport costs"),
|
35
|
+
{
|
36
|
+
:title => _("Fixed travel"),
|
37
|
+
:type => :toggle
|
38
|
+
},
|
39
|
+
{
|
40
|
+
:title => _("Int. work"),
|
41
|
+
:type => :toggle
|
42
|
+
},
|
43
|
+
{
|
44
|
+
:title => _("Sync?"),
|
45
|
+
:type => :toggle
|
46
|
+
},
|
47
|
+
{
|
48
|
+
:title => _("Task"),
|
49
|
+
:type => :combo,
|
50
|
+
:model => task_ls,
|
51
|
+
:has_entry => false
|
52
|
+
},
|
53
|
+
_("Sync time")
|
54
|
+
])
|
55
|
+
|
56
|
+
#Make columns editable.
|
57
|
+
Knj::Gtk2::Tv.editable_text_renderers_to_model(
|
58
|
+
:ob => @args[:oata].ob,
|
59
|
+
:tv => @gui["tvTimelogs"],
|
60
|
+
:model_class => :Timelog,
|
61
|
+
:renderers => init_data[:renderers],
|
62
|
+
:change_before => proc{ @dont_reload = true },
|
63
|
+
:change_after => proc{ @dont_reload = false; self.update_totals },
|
64
|
+
:cols => {
|
65
|
+
1 => :descr,
|
66
|
+
2 => {:col => :timestamp, :type => :datetime},
|
67
|
+
3 => {:col => :time, :type => :time_as_sec},
|
68
|
+
4 => {:col => :time_transport, :type => :time_as_sec},
|
69
|
+
5 => {:col => :transportlength, :type => :int},
|
70
|
+
6 => {:col => :transportdescription},
|
71
|
+
7 => {:col => :transportcosts, :type => :human_number, :decimals => 2},
|
72
|
+
8 => {:col => :travelfixed},
|
73
|
+
9 => {:col => :workinternal},
|
74
|
+
10 => {:col => :sync_need},
|
75
|
+
11 => {
|
76
|
+
:col => :task_id,
|
77
|
+
:value_callback => lambda{ |data|
|
78
|
+
task = @args[:oata].ob.get_by(:Task, {"title" => data[:value]})
|
79
|
+
|
80
|
+
if !task
|
81
|
+
return 0
|
82
|
+
else
|
83
|
+
return task.id
|
84
|
+
end
|
85
|
+
},
|
86
|
+
:value_set_callback => proc{ |data| data[:model].task_name }
|
87
|
+
},
|
88
|
+
12 => {:col => :time_sync, :type => :time_as_sec}
|
89
|
+
}
|
90
|
+
)
|
91
|
+
@gui["tvTimelogs"].columns[0].visible = false
|
92
|
+
|
93
|
+
|
94
|
+
=begin
|
14
95
|
rowc = 1
|
15
96
|
@args[:oata].ob.list(:Timelog, {"sync_need" => 1, "task_id_not" => 0}) do |timelog|
|
16
|
-
#Read time and transport from timelog.
|
17
|
-
time = timelog[:time].to_i
|
18
|
-
transport = timelog[:time_transport].to_i
|
19
|
-
|
20
|
-
#If transport is logged, then the work if offsite. It should be rounded up by 30 min. Else 15 min. round up.
|
21
|
-
if transport > 0
|
22
|
-
roundup = 1800
|
23
|
-
else
|
24
|
-
roundup = 900
|
25
|
-
end
|
26
97
|
|
27
|
-
#Do the actual counting.
|
28
|
-
count_rounded_time = 0
|
29
|
-
loop do
|
30
|
-
break if count_rounded_time >= time
|
31
|
-
count_rounded_time += roundup
|
32
|
-
end
|
33
98
|
|
34
99
|
#Spawn widgets.
|
35
100
|
timelog_label = Gtk::Label.new(timelog[:descr])
|
@@ -42,6 +107,7 @@ class Openall_time_applet::Gui::Win_sync_overview
|
|
42
107
|
|
43
108
|
sync_time_text = Gtk::Entry.new
|
44
109
|
sync_time_text.text = Knj::Strings.secs_to_human_time_str(count_rounded_time)
|
110
|
+
sync_time_text.signal_connect(:changed, &self.method(:on_syncTimeText_changed))
|
45
111
|
@sync_time_text_widgets[timelog.id] = sync_time_text
|
46
112
|
|
47
113
|
#Attach widgets in table.
|
@@ -51,8 +117,14 @@ class Openall_time_applet::Gui::Win_sync_overview
|
|
51
117
|
|
52
118
|
rowc += 1
|
53
119
|
end
|
120
|
+
=end
|
54
121
|
|
55
|
-
|
122
|
+
self.reload_timelogs
|
123
|
+
self.update_totals
|
124
|
+
|
125
|
+
@reload_id = @args[:oata].ob.connect("object" => :Timelog, "signals" => ["add", "update", "delete"], &self.method(:reload_timelogs))
|
126
|
+
|
127
|
+
if @timelogs_count <= 0
|
56
128
|
#Show error-message and destroy the window, if no timelogs was to be synced.
|
57
129
|
Knj::Gtk2.msgbox("msg" => _("There is nothing to sync at this time."), "run" => false)
|
58
130
|
@gui["window"].destroy
|
@@ -62,20 +134,53 @@ class Openall_time_applet::Gui::Win_sync_overview
|
|
62
134
|
end
|
63
135
|
end
|
64
136
|
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
137
|
+
def reload_timelogs
|
138
|
+
return nil if @dont_reload or @gui["tvTimelogs"].destroyed?
|
139
|
+
@gui["tvTimelogs"].model.clear
|
140
|
+
@timelogs_count = 0
|
141
|
+
@args[:oata].ob.list(:Timelog, {"sync_need" => 1, "task_id_not" => 0, "orderby" => "timestamp"}) do |timelog|
|
142
|
+
#Read time and transport from timelog.
|
143
|
+
time = timelog[:time].to_i
|
144
|
+
transport = timelog[:time_transport].to_i
|
145
|
+
|
146
|
+
#If transport is logged, then the work if offsite. It should be rounded up by 30 min. Else 15 min. round up.
|
147
|
+
if transport > 0
|
148
|
+
roundup = 1800
|
149
|
+
else
|
150
|
+
roundup = 900
|
151
|
+
end
|
152
|
+
|
153
|
+
#Do the actual counting.
|
154
|
+
count_rounded_time = 0
|
155
|
+
loop do
|
156
|
+
break if count_rounded_time >= time
|
157
|
+
count_rounded_time += roundup
|
77
158
|
end
|
78
159
|
|
160
|
+
#Set sync-time on timelog.
|
161
|
+
timelog[:time_sync] = count_rounded_time
|
162
|
+
|
163
|
+
Knj::Gtk2::Tv.append(@gui["tvTimelogs"], [
|
164
|
+
timelog.id,
|
165
|
+
timelog[:descr],
|
166
|
+
timelog.timestamp_str,
|
167
|
+
timelog.time_as_human,
|
168
|
+
timelog.time_transport_as_human,
|
169
|
+
Knj::Locales.number_out(timelog[:transportlength], 0),
|
170
|
+
timelog.transport_descr_short,
|
171
|
+
Knj::Locales.number_out(timelog[:transportcosts], 2),
|
172
|
+
Knj::Strings.yn_str(timelog[:travelfixed], true, false),
|
173
|
+
Knj::Strings.yn_str(timelog[:workinternal], true, false),
|
174
|
+
Knj::Strings.yn_str(timelog[:sync_need], true, false),
|
175
|
+
timelog.task_name,
|
176
|
+
Knj::Strings.secs_to_human_time_str(count_rounded_time)
|
177
|
+
])
|
178
|
+
@timelogs_count += 1
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def on_btnSync_clicked
|
183
|
+
begin
|
79
184
|
#Destroy this window and start syncing for real.
|
80
185
|
@gui["window"].destroy
|
81
186
|
@args[:oata].sync_real
|
@@ -83,4 +188,25 @@ class Openall_time_applet::Gui::Win_sync_overview
|
|
83
188
|
Knj::Gtk2.msgbox(Knj::Errors.error_str(e))
|
84
189
|
end
|
85
190
|
end
|
191
|
+
|
192
|
+
def update_totals
|
193
|
+
total_secs = 0
|
194
|
+
|
195
|
+
@gui["tvTimelogs"].model.each do |model, path, iter|
|
196
|
+
time_val = @gui["tvTimelogs"].model.get_value(iter, 12)
|
197
|
+
|
198
|
+
begin
|
199
|
+
total_secs += Knj::Strings.human_time_str_to_secs(time_val)
|
200
|
+
rescue
|
201
|
+
#ignore - user is properly entering stuff.
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
@gui["labTotal"].markup = "<b>#{_("Total hours:")}</b> #{Knj::Strings.secs_to_human_time_str(total_secs)}"
|
206
|
+
end
|
207
|
+
|
208
|
+
def on_window_destroy
|
209
|
+
#Unconnect reload-event. Else it will crash on call to destroyed object. Also frees up various ressources.
|
210
|
+
@args[:oata].ob.unconnect("object" => :Timelog, "conn_id" => @reload_id)
|
211
|
+
end
|
86
212
|
end
|
data/lib/openall_time_applet.rb
CHANGED
@@ -239,18 +239,6 @@ class Openall_time_applet
|
|
239
239
|
end
|
240
240
|
end
|
241
241
|
|
242
|
-
def show_timelog_new
|
243
|
-
Knj::Gtk2::Window.unique!("timelog_new") do
|
244
|
-
Openall_time_applet::Gui::Win_timelog_edit.new(:oata => self)
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
def show_timelog_edit(timelog)
|
249
|
-
Knj::Gtk2::Window.unique!("timelog_edit_#{timelog.id}") do
|
250
|
-
Openall_time_applet::Gui::Win_timelog_edit.new(:oata => self, :timelog => timelog)
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
242
|
def show_overview
|
255
243
|
Knj::Gtk2::Window.unique!("overview") do
|
256
244
|
Openall_time_applet::Gui::Win_overview.new(:oata => self)
|
@@ -284,7 +272,7 @@ class Openall_time_applet
|
|
284
272
|
|
285
273
|
#Synchronizes organisations, tasks and worktimes.
|
286
274
|
def sync_static(args = nil)
|
287
|
-
sw = Knj::Gtk2::StatusWindow.new
|
275
|
+
sw = Knj::Gtk2::StatusWindow.new("transient_for" => args["transient_for"])
|
288
276
|
|
289
277
|
return Knj::Thread.new do
|
290
278
|
begin
|
@@ -301,11 +289,11 @@ class Openall_time_applet
|
|
301
289
|
sw.percent = 1
|
302
290
|
|
303
291
|
sleep 1 if !block_given?
|
304
|
-
sw.destroy
|
292
|
+
sw.destroy if sw
|
305
293
|
sw = nil
|
306
294
|
yield if block_given?
|
307
295
|
rescue => e
|
308
|
-
sw.destroy
|
296
|
+
sw.destroy if sw
|
309
297
|
sw = nil
|
310
298
|
Knj::Gtk2.msgbox("msg" => Knj::Errors.error_str(e), "type" => "warning", "title" => _("Error"), "run" => false)
|
311
299
|
ensure
|
@@ -353,6 +341,7 @@ class Openall_time_applet
|
|
353
341
|
:time => @timelog_active[:time].to_i + secs_passed,
|
354
342
|
:sync_need => 1
|
355
343
|
)
|
344
|
+
@timelog_logged_time[:timestamp_end] = Time.now
|
356
345
|
end
|
357
346
|
|
358
347
|
@timelog_active = nil
|
@@ -362,10 +351,33 @@ class Openall_time_applet
|
|
362
351
|
|
363
352
|
#Sets a new timelog to track. Stops tracking of previous timelog if already tracking.
|
364
353
|
def timelog_active=(timelog)
|
365
|
-
|
354
|
+
begin
|
355
|
+
#Check if there has been logged time another day - if so, clone it and begin logging on the clone instead.
|
356
|
+
tlt = @ob.list(:Timelog_logged_time, {
|
357
|
+
"timelog" => timelog,
|
358
|
+
"timestamp_start_day_not" => Time.now,
|
359
|
+
"limit" => 1
|
360
|
+
})
|
361
|
+
if !tlt.empty?
|
362
|
+
timelog = @ob.add(:Timelog, {
|
363
|
+
:task_id => timelog[:task_id],
|
364
|
+
:timestamp => Time.now,
|
365
|
+
:descr => timelog[:descr],
|
366
|
+
:transportdescription => timelog[:transportdescription],
|
367
|
+
:workinternal => timelog[:workinternal],
|
368
|
+
:timetype => timelog[:timetype]
|
369
|
+
})
|
370
|
+
#raise sprintf(_("You have already logged on this timelog on %s"), tlt.first.timestamp_start.out)
|
371
|
+
end
|
372
|
+
|
373
|
+
self.timelog_stop_tracking
|
374
|
+
@timelog_logged_time = @ob.add(:Timelog_logged_time, {:timelog_id => timelog.id})
|
375
|
+
@timelog_active = timelog
|
376
|
+
@timelog_active_time = Time.new
|
377
|
+
rescue => e
|
378
|
+
Knj::Gtk2.msgbox("msg" => Knj::Errors.error_str(e), "type" => "warning", "title" => _("Error"), "run" => false)
|
379
|
+
end
|
366
380
|
|
367
|
-
@timelog_active = timelog
|
368
|
-
@timelog_active_time = Time.new
|
369
381
|
@ti.update_icon if @ti
|
370
382
|
end
|
371
383
|
|
data/models/timelog.rb
CHANGED
@@ -3,6 +3,10 @@ class Openall_time_applet::Models::Timelog < Knj::Datarow
|
|
3
3
|
:Task
|
4
4
|
]
|
5
5
|
|
6
|
+
has_many [
|
7
|
+
{:class => :Timelog_logged_time, :col => :timelog_id, :method => :logged_times, :autodelete => true}
|
8
|
+
]
|
9
|
+
|
6
10
|
def initialize(*args, &block)
|
7
11
|
super(*args, &block)
|
8
12
|
|
@@ -22,7 +26,7 @@ class Openall_time_applet::Models::Timelog < Knj::Datarow
|
|
22
26
|
args[:oata].oa_conn do |conn|
|
23
27
|
#Go through timelogs that needs syncing and has a task set.
|
24
28
|
self.ob.list(:Timelog, {"sync_need" => 1, "task_id_not" => 0}) do |timelog|
|
25
|
-
secs_sum = timelog[:
|
29
|
+
secs_sum = timelog[:time_sync].to_i + timelog[:time_transport].to_i
|
26
30
|
next if secs_sum <= 0
|
27
31
|
|
28
32
|
#The timelog has not yet been created in OpenAll - create it!
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class Openall_time_applet::Models::Timelog_logged_time < Knj::Datarow
|
2
|
+
has_one [
|
3
|
+
{:class => :Timelog, :col => :timelog_id, :method => :timelog, :depends => true}
|
4
|
+
]
|
5
|
+
|
6
|
+
def self.add(d)
|
7
|
+
d.data[:timestamp_start] = Time.now if !d.data[:timestamp_start]
|
8
|
+
end
|
9
|
+
end
|
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.15"
|
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-06-
|
12
|
+
s.date = %q{2012-06-25}
|
13
13
|
s.default_executable = %q{openall_time_applet.rb}
|
14
14
|
s.description = %q{Off-line time-tracking for OpenAll with syncing when online.}
|
15
15
|
s.email = %q{k@spernj.org}
|
@@ -40,14 +40,11 @@ Gem::Specification.new do |s|
|
|
40
40
|
"glade/win_overview.glade",
|
41
41
|
"glade/win_preferences.glade",
|
42
42
|
"glade/win_sync_overview.glade",
|
43
|
-
"glade/win_timelog_edit.glade",
|
44
43
|
"glade/win_worktime_overview.glade",
|
45
44
|
"gui/trayicon.rb",
|
46
45
|
"gui/win_main.rb",
|
47
|
-
"gui/win_overview.rb",
|
48
46
|
"gui/win_preferences.rb",
|
49
47
|
"gui/win_sync_overview.rb",
|
50
|
-
"gui/win_timelog_edit.rb",
|
51
48
|
"gui/win_worktime_overview.rb",
|
52
49
|
"lib/openall_time_applet.rb",
|
53
50
|
"locales/da_DK/LC_MESSAGES/default.mo",
|
@@ -55,6 +52,7 @@ Gem::Specification.new do |s|
|
|
55
52
|
"models/organisation.rb",
|
56
53
|
"models/task.rb",
|
57
54
|
"models/timelog.rb",
|
55
|
+
"models/timelog_logged_time.rb",
|
58
56
|
"models/worktime.rb",
|
59
57
|
"openall_time_applet.gemspec",
|
60
58
|
"spec/openall_time_applet_spec.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.15
|
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-06-
|
13
|
+
date: 2012-06-25 00:00:00 +02:00
|
14
14
|
default_executable: openall_time_applet.rb
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -165,14 +165,11 @@ files:
|
|
165
165
|
- glade/win_overview.glade
|
166
166
|
- glade/win_preferences.glade
|
167
167
|
- glade/win_sync_overview.glade
|
168
|
-
- glade/win_timelog_edit.glade
|
169
168
|
- glade/win_worktime_overview.glade
|
170
169
|
- gui/trayicon.rb
|
171
170
|
- gui/win_main.rb
|
172
|
-
- gui/win_overview.rb
|
173
171
|
- gui/win_preferences.rb
|
174
172
|
- gui/win_sync_overview.rb
|
175
|
-
- gui/win_timelog_edit.rb
|
176
173
|
- gui/win_worktime_overview.rb
|
177
174
|
- lib/openall_time_applet.rb
|
178
175
|
- locales/da_DK/LC_MESSAGES/default.mo
|
@@ -180,6 +177,7 @@ files:
|
|
180
177
|
- models/organisation.rb
|
181
178
|
- models/task.rb
|
182
179
|
- models/timelog.rb
|
180
|
+
- models/timelog_logged_time.rb
|
183
181
|
- models/worktime.rb
|
184
182
|
- openall_time_applet.gemspec
|
185
183
|
- spec/openall_time_applet_spec.rb
|
@@ -198,7 +196,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
198
196
|
requirements:
|
199
197
|
- - ">="
|
200
198
|
- !ruby/object:Gem::Version
|
201
|
-
hash:
|
199
|
+
hash: 1181471258583995936
|
202
200
|
segments:
|
203
201
|
- 0
|
204
202
|
version: "0"
|
@@ -1,440 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<interface>
|
3
|
-
<requires lib="gtk+" version="2.24"/>
|
4
|
-
<!-- interface-naming-policy project-wide -->
|
5
|
-
<object class="GtkWindow" id="window">
|
6
|
-
<property name="can_focus">False</property>
|
7
|
-
<property name="title" translatable="yes">Timelog</property>
|
8
|
-
<property name="window_position">center</property>
|
9
|
-
<property name="default_width">360</property>
|
10
|
-
<child>
|
11
|
-
<object class="GtkVBox" id="vbox1">
|
12
|
-
<property name="visible">True</property>
|
13
|
-
<property name="can_focus">False</property>
|
14
|
-
<child>
|
15
|
-
<object class="GtkFrame" id="frame1">
|
16
|
-
<property name="visible">True</property>
|
17
|
-
<property name="can_focus">False</property>
|
18
|
-
<property name="label_xalign">0</property>
|
19
|
-
<property name="shadow_type">none</property>
|
20
|
-
<child>
|
21
|
-
<object class="GtkAlignment" id="alignment1">
|
22
|
-
<property name="visible">True</property>
|
23
|
-
<property name="can_focus">False</property>
|
24
|
-
<property name="left_padding">12</property>
|
25
|
-
<child>
|
26
|
-
<object class="GtkTable" id="table1">
|
27
|
-
<property name="visible">True</property>
|
28
|
-
<property name="can_focus">False</property>
|
29
|
-
<property name="n_rows">13</property>
|
30
|
-
<property name="n_columns">2</property>
|
31
|
-
<property name="column_spacing">3</property>
|
32
|
-
<property name="row_spacing">3</property>
|
33
|
-
<child>
|
34
|
-
<object class="GtkLabel" id="label3">
|
35
|
-
<property name="visible">True</property>
|
36
|
-
<property name="can_focus">False</property>
|
37
|
-
<property name="xalign">0</property>
|
38
|
-
<property name="label" translatable="yes">Description</property>
|
39
|
-
</object>
|
40
|
-
<packing>
|
41
|
-
<property name="x_options">GTK_FILL</property>
|
42
|
-
<property name="y_options">GTK_FILL</property>
|
43
|
-
</packing>
|
44
|
-
</child>
|
45
|
-
<child>
|
46
|
-
<object class="GtkLabel" id="label4">
|
47
|
-
<property name="visible">True</property>
|
48
|
-
<property name="can_focus">False</property>
|
49
|
-
<property name="xalign">0</property>
|
50
|
-
<property name="label" translatable="yes">Time</property>
|
51
|
-
</object>
|
52
|
-
<packing>
|
53
|
-
<property name="top_attach">1</property>
|
54
|
-
<property name="bottom_attach">2</property>
|
55
|
-
<property name="x_options">GTK_FILL</property>
|
56
|
-
<property name="y_options">GTK_FILL</property>
|
57
|
-
</packing>
|
58
|
-
</child>
|
59
|
-
<child>
|
60
|
-
<object class="GtkEntry" id="txtTime">
|
61
|
-
<property name="visible">True</property>
|
62
|
-
<property name="can_focus">True</property>
|
63
|
-
<property name="invisible_char">•</property>
|
64
|
-
<property name="primary_icon_activatable">False</property>
|
65
|
-
<property name="secondary_icon_activatable">False</property>
|
66
|
-
<property name="primary_icon_sensitive">True</property>
|
67
|
-
<property name="secondary_icon_sensitive">True</property>
|
68
|
-
</object>
|
69
|
-
<packing>
|
70
|
-
<property name="left_attach">1</property>
|
71
|
-
<property name="right_attach">2</property>
|
72
|
-
<property name="top_attach">1</property>
|
73
|
-
<property name="bottom_attach">2</property>
|
74
|
-
</packing>
|
75
|
-
</child>
|
76
|
-
<child>
|
77
|
-
<object class="GtkLabel" id="label5">
|
78
|
-
<property name="visible">True</property>
|
79
|
-
<property name="can_focus">False</property>
|
80
|
-
<property name="xalign">0</property>
|
81
|
-
<property name="label" translatable="yes">Transport</property>
|
82
|
-
</object>
|
83
|
-
<packing>
|
84
|
-
<property name="top_attach">2</property>
|
85
|
-
<property name="bottom_attach">3</property>
|
86
|
-
<property name="x_options">GTK_FILL</property>
|
87
|
-
<property name="y_options">GTK_FILL</property>
|
88
|
-
</packing>
|
89
|
-
</child>
|
90
|
-
<child>
|
91
|
-
<object class="GtkEntry" id="txtTimeTransport">
|
92
|
-
<property name="visible">True</property>
|
93
|
-
<property name="can_focus">True</property>
|
94
|
-
<property name="invisible_char">•</property>
|
95
|
-
<property name="primary_icon_activatable">False</property>
|
96
|
-
<property name="secondary_icon_activatable">False</property>
|
97
|
-
<property name="primary_icon_sensitive">True</property>
|
98
|
-
<property name="secondary_icon_sensitive">True</property>
|
99
|
-
</object>
|
100
|
-
<packing>
|
101
|
-
<property name="left_attach">1</property>
|
102
|
-
<property name="right_attach">2</property>
|
103
|
-
<property name="top_attach">2</property>
|
104
|
-
<property name="bottom_attach">3</property>
|
105
|
-
</packing>
|
106
|
-
</child>
|
107
|
-
<child>
|
108
|
-
<object class="GtkLabel" id="label6">
|
109
|
-
<property name="visible">True</property>
|
110
|
-
<property name="can_focus">False</property>
|
111
|
-
<property name="xalign">0</property>
|
112
|
-
<property name="label" translatable="yes">Task</property>
|
113
|
-
</object>
|
114
|
-
<packing>
|
115
|
-
<property name="top_attach">10</property>
|
116
|
-
<property name="bottom_attach">11</property>
|
117
|
-
<property name="x_options">GTK_FILL</property>
|
118
|
-
<property name="y_options">GTK_FILL</property>
|
119
|
-
</packing>
|
120
|
-
</child>
|
121
|
-
<child>
|
122
|
-
<object class="GtkComboBox" id="cbTask">
|
123
|
-
<property name="visible">True</property>
|
124
|
-
<property name="can_focus">False</property>
|
125
|
-
</object>
|
126
|
-
<packing>
|
127
|
-
<property name="left_attach">1</property>
|
128
|
-
<property name="right_attach">2</property>
|
129
|
-
<property name="top_attach">10</property>
|
130
|
-
<property name="bottom_attach">11</property>
|
131
|
-
</packing>
|
132
|
-
</child>
|
133
|
-
<child>
|
134
|
-
<object class="GtkCheckButton" id="cbShouldSync">
|
135
|
-
<property name="label" translatable="yes">Should sync</property>
|
136
|
-
<property name="visible">True</property>
|
137
|
-
<property name="can_focus">True</property>
|
138
|
-
<property name="receives_default">False</property>
|
139
|
-
<property name="use_action_appearance">False</property>
|
140
|
-
<property name="draw_indicator">True</property>
|
141
|
-
</object>
|
142
|
-
<packing>
|
143
|
-
<property name="right_attach">2</property>
|
144
|
-
<property name="top_attach">11</property>
|
145
|
-
<property name="bottom_attach">12</property>
|
146
|
-
<property name="x_options">GTK_FILL</property>
|
147
|
-
<property name="y_options">GTK_FILL</property>
|
148
|
-
</packing>
|
149
|
-
</child>
|
150
|
-
<child>
|
151
|
-
<object class="GtkCheckButton" id="cbStartTracking">
|
152
|
-
<property name="label" translatable="yes">Start tracking after saving</property>
|
153
|
-
<property name="visible">True</property>
|
154
|
-
<property name="can_focus">True</property>
|
155
|
-
<property name="receives_default">False</property>
|
156
|
-
<property name="use_action_appearance">False</property>
|
157
|
-
<property name="draw_indicator">True</property>
|
158
|
-
</object>
|
159
|
-
<packing>
|
160
|
-
<property name="right_attach">2</property>
|
161
|
-
<property name="top_attach">12</property>
|
162
|
-
<property name="bottom_attach">13</property>
|
163
|
-
</packing>
|
164
|
-
</child>
|
165
|
-
<child>
|
166
|
-
<object class="GtkEntry" id="txtDescr">
|
167
|
-
<property name="visible">True</property>
|
168
|
-
<property name="can_focus">True</property>
|
169
|
-
<property name="invisible_char">•</property>
|
170
|
-
<property name="primary_icon_activatable">False</property>
|
171
|
-
<property name="secondary_icon_activatable">False</property>
|
172
|
-
<property name="primary_icon_sensitive">True</property>
|
173
|
-
<property name="secondary_icon_sensitive">True</property>
|
174
|
-
</object>
|
175
|
-
<packing>
|
176
|
-
<property name="left_attach">1</property>
|
177
|
-
<property name="right_attach">2</property>
|
178
|
-
</packing>
|
179
|
-
</child>
|
180
|
-
<child>
|
181
|
-
<object class="GtkLabel" id="label7">
|
182
|
-
<property name="visible">True</property>
|
183
|
-
<property name="can_focus">False</property>
|
184
|
-
<property name="xalign">0</property>
|
185
|
-
<property name="label" translatable="yes">Transport length</property>
|
186
|
-
</object>
|
187
|
-
<packing>
|
188
|
-
<property name="top_attach">3</property>
|
189
|
-
<property name="bottom_attach">4</property>
|
190
|
-
<property name="x_options">GTK_FILL</property>
|
191
|
-
<property name="y_options">GTK_FILL</property>
|
192
|
-
</packing>
|
193
|
-
</child>
|
194
|
-
<child>
|
195
|
-
<object class="GtkLabel" id="label8">
|
196
|
-
<property name="visible">True</property>
|
197
|
-
<property name="can_focus">False</property>
|
198
|
-
<property name="xalign">0</property>
|
199
|
-
<property name="label" translatable="yes">Transport costs</property>
|
200
|
-
</object>
|
201
|
-
<packing>
|
202
|
-
<property name="top_attach">4</property>
|
203
|
-
<property name="bottom_attach">5</property>
|
204
|
-
<property name="x_options">GTK_FILL</property>
|
205
|
-
<property name="y_options">GTK_FILL</property>
|
206
|
-
</packing>
|
207
|
-
</child>
|
208
|
-
<child>
|
209
|
-
<object class="GtkEntry" id="txtTransportLength">
|
210
|
-
<property name="visible">True</property>
|
211
|
-
<property name="can_focus">True</property>
|
212
|
-
<property name="invisible_char">•</property>
|
213
|
-
<property name="primary_icon_activatable">False</property>
|
214
|
-
<property name="secondary_icon_activatable">False</property>
|
215
|
-
<property name="primary_icon_sensitive">True</property>
|
216
|
-
<property name="secondary_icon_sensitive">True</property>
|
217
|
-
</object>
|
218
|
-
<packing>
|
219
|
-
<property name="left_attach">1</property>
|
220
|
-
<property name="right_attach">2</property>
|
221
|
-
<property name="top_attach">3</property>
|
222
|
-
<property name="bottom_attach">4</property>
|
223
|
-
</packing>
|
224
|
-
</child>
|
225
|
-
<child>
|
226
|
-
<object class="GtkEntry" id="txtTransportCosts">
|
227
|
-
<property name="visible">True</property>
|
228
|
-
<property name="can_focus">True</property>
|
229
|
-
<property name="invisible_char">•</property>
|
230
|
-
<property name="primary_icon_activatable">False</property>
|
231
|
-
<property name="secondary_icon_activatable">False</property>
|
232
|
-
<property name="primary_icon_sensitive">True</property>
|
233
|
-
<property name="secondary_icon_sensitive">True</property>
|
234
|
-
</object>
|
235
|
-
<packing>
|
236
|
-
<property name="left_attach">1</property>
|
237
|
-
<property name="right_attach">2</property>
|
238
|
-
<property name="top_attach">4</property>
|
239
|
-
<property name="bottom_attach">5</property>
|
240
|
-
</packing>
|
241
|
-
</child>
|
242
|
-
<child>
|
243
|
-
<object class="GtkLabel" id="label9">
|
244
|
-
<property name="visible">True</property>
|
245
|
-
<property name="can_focus">False</property>
|
246
|
-
<property name="xalign">0</property>
|
247
|
-
<property name="label" translatable="yes">Transport description</property>
|
248
|
-
</object>
|
249
|
-
<packing>
|
250
|
-
<property name="top_attach">5</property>
|
251
|
-
<property name="bottom_attach">6</property>
|
252
|
-
<property name="x_options">GTK_FILL</property>
|
253
|
-
<property name="y_options">GTK_FILL</property>
|
254
|
-
</packing>
|
255
|
-
</child>
|
256
|
-
<child>
|
257
|
-
<object class="GtkEntry" id="txtTransportDescr">
|
258
|
-
<property name="visible">True</property>
|
259
|
-
<property name="can_focus">True</property>
|
260
|
-
<property name="invisible_char">•</property>
|
261
|
-
<property name="primary_icon_activatable">False</property>
|
262
|
-
<property name="secondary_icon_activatable">False</property>
|
263
|
-
<property name="primary_icon_sensitive">True</property>
|
264
|
-
<property name="secondary_icon_sensitive">True</property>
|
265
|
-
</object>
|
266
|
-
<packing>
|
267
|
-
<property name="left_attach">1</property>
|
268
|
-
<property name="right_attach">2</property>
|
269
|
-
<property name="top_attach">5</property>
|
270
|
-
<property name="bottom_attach">6</property>
|
271
|
-
</packing>
|
272
|
-
</child>
|
273
|
-
<child>
|
274
|
-
<object class="GtkCheckButton" id="cbWorkInternal">
|
275
|
-
<property name="label" translatable="yes">Internal work</property>
|
276
|
-
<property name="visible">True</property>
|
277
|
-
<property name="can_focus">True</property>
|
278
|
-
<property name="receives_default">False</property>
|
279
|
-
<property name="use_action_appearance">False</property>
|
280
|
-
<property name="draw_indicator">True</property>
|
281
|
-
</object>
|
282
|
-
<packing>
|
283
|
-
<property name="right_attach">2</property>
|
284
|
-
<property name="top_attach">6</property>
|
285
|
-
<property name="bottom_attach">7</property>
|
286
|
-
</packing>
|
287
|
-
</child>
|
288
|
-
<child>
|
289
|
-
<object class="GtkCheckButton" id="cbTravelFixed">
|
290
|
-
<property name="label" translatable="yes">Fixed travel</property>
|
291
|
-
<property name="visible">True</property>
|
292
|
-
<property name="can_focus">True</property>
|
293
|
-
<property name="receives_default">False</property>
|
294
|
-
<property name="use_action_appearance">False</property>
|
295
|
-
<property name="draw_indicator">True</property>
|
296
|
-
</object>
|
297
|
-
<packing>
|
298
|
-
<property name="right_attach">2</property>
|
299
|
-
<property name="top_attach">7</property>
|
300
|
-
<property name="bottom_attach">8</property>
|
301
|
-
<property name="x_options">GTK_FILL</property>
|
302
|
-
<property name="y_options">GTK_FILL</property>
|
303
|
-
</packing>
|
304
|
-
</child>
|
305
|
-
<child>
|
306
|
-
<object class="GtkLabel" id="label10">
|
307
|
-
<property name="visible">True</property>
|
308
|
-
<property name="can_focus">False</property>
|
309
|
-
<property name="xalign">0</property>
|
310
|
-
<property name="label" translatable="yes">Time type</property>
|
311
|
-
</object>
|
312
|
-
<packing>
|
313
|
-
<property name="top_attach">8</property>
|
314
|
-
<property name="bottom_attach">9</property>
|
315
|
-
<property name="x_options">GTK_FILL</property>
|
316
|
-
<property name="y_options">GTK_FILL</property>
|
317
|
-
</packing>
|
318
|
-
</child>
|
319
|
-
<child>
|
320
|
-
<object class="GtkComboBox" id="cbTimeType">
|
321
|
-
<property name="visible">True</property>
|
322
|
-
<property name="can_focus">False</property>
|
323
|
-
</object>
|
324
|
-
<packing>
|
325
|
-
<property name="left_attach">1</property>
|
326
|
-
<property name="right_attach">2</property>
|
327
|
-
<property name="top_attach">8</property>
|
328
|
-
<property name="bottom_attach">9</property>
|
329
|
-
</packing>
|
330
|
-
</child>
|
331
|
-
<child>
|
332
|
-
<object class="GtkLabel" id="label11">
|
333
|
-
<property name="visible">True</property>
|
334
|
-
<property name="can_focus">False</property>
|
335
|
-
<property name="xalign">0</property>
|
336
|
-
<property name="label" translatable="yes">Timestamp</property>
|
337
|
-
</object>
|
338
|
-
<packing>
|
339
|
-
<property name="top_attach">9</property>
|
340
|
-
<property name="bottom_attach">10</property>
|
341
|
-
<property name="x_options">GTK_FILL</property>
|
342
|
-
<property name="y_options">GTK_FILL</property>
|
343
|
-
</packing>
|
344
|
-
</child>
|
345
|
-
<child>
|
346
|
-
<object class="GtkEntry" id="txtTimestamp">
|
347
|
-
<property name="visible">True</property>
|
348
|
-
<property name="can_focus">True</property>
|
349
|
-
<property name="invisible_char">•</property>
|
350
|
-
<property name="primary_icon_activatable">False</property>
|
351
|
-
<property name="secondary_icon_activatable">False</property>
|
352
|
-
<property name="primary_icon_sensitive">True</property>
|
353
|
-
<property name="secondary_icon_sensitive">True</property>
|
354
|
-
</object>
|
355
|
-
<packing>
|
356
|
-
<property name="left_attach">1</property>
|
357
|
-
<property name="right_attach">2</property>
|
358
|
-
<property name="top_attach">9</property>
|
359
|
-
<property name="bottom_attach">10</property>
|
360
|
-
</packing>
|
361
|
-
</child>
|
362
|
-
</object>
|
363
|
-
</child>
|
364
|
-
</object>
|
365
|
-
</child>
|
366
|
-
<child type="label">
|
367
|
-
<object class="GtkLabel" id="label1">
|
368
|
-
<property name="visible">True</property>
|
369
|
-
<property name="can_focus">False</property>
|
370
|
-
<property name="label" translatable="yes"><b>Timelog</b></property>
|
371
|
-
<property name="use_markup">True</property>
|
372
|
-
</object>
|
373
|
-
</child>
|
374
|
-
</object>
|
375
|
-
<packing>
|
376
|
-
<property name="expand">False</property>
|
377
|
-
<property name="fill">True</property>
|
378
|
-
<property name="position">0</property>
|
379
|
-
</packing>
|
380
|
-
</child>
|
381
|
-
<child>
|
382
|
-
<object class="GtkHButtonBox" id="hbuttonbox1">
|
383
|
-
<property name="visible">True</property>
|
384
|
-
<property name="can_focus">False</property>
|
385
|
-
<property name="spacing">3</property>
|
386
|
-
<property name="layout_style">end</property>
|
387
|
-
<child>
|
388
|
-
<object class="GtkButton" id="btnRemove">
|
389
|
-
<property name="label">gtk-remove</property>
|
390
|
-
<property name="visible">True</property>
|
391
|
-
<property name="can_focus">True</property>
|
392
|
-
<property name="receives_default">True</property>
|
393
|
-
<property name="use_action_appearance">False</property>
|
394
|
-
<property name="use_stock">True</property>
|
395
|
-
<signal name="clicked" handler="on_btnRemove_clicked" swapped="no"/>
|
396
|
-
</object>
|
397
|
-
<packing>
|
398
|
-
<property name="expand">False</property>
|
399
|
-
<property name="fill">False</property>
|
400
|
-
<property name="position">0</property>
|
401
|
-
</packing>
|
402
|
-
</child>
|
403
|
-
<child>
|
404
|
-
<object class="GtkButton" id="btnSave">
|
405
|
-
<property name="label">gtk-save</property>
|
406
|
-
<property name="visible">True</property>
|
407
|
-
<property name="can_focus">True</property>
|
408
|
-
<property name="receives_default">True</property>
|
409
|
-
<property name="use_action_appearance">False</property>
|
410
|
-
<property name="use_stock">True</property>
|
411
|
-
<signal name="clicked" handler="on_btnSave_clicked" swapped="no"/>
|
412
|
-
</object>
|
413
|
-
<packing>
|
414
|
-
<property name="expand">False</property>
|
415
|
-
<property name="fill">False</property>
|
416
|
-
<property name="position">1</property>
|
417
|
-
</packing>
|
418
|
-
</child>
|
419
|
-
</object>
|
420
|
-
<packing>
|
421
|
-
<property name="expand">False</property>
|
422
|
-
<property name="fill">True</property>
|
423
|
-
<property name="position">1</property>
|
424
|
-
</packing>
|
425
|
-
</child>
|
426
|
-
<child>
|
427
|
-
<object class="GtkLabel" id="label2">
|
428
|
-
<property name="visible">True</property>
|
429
|
-
<property name="can_focus">False</property>
|
430
|
-
</object>
|
431
|
-
<packing>
|
432
|
-
<property name="expand">True</property>
|
433
|
-
<property name="fill">True</property>
|
434
|
-
<property name="position">2</property>
|
435
|
-
</packing>
|
436
|
-
</child>
|
437
|
-
</object>
|
438
|
-
</child>
|
439
|
-
</object>
|
440
|
-
</interface>
|
data/gui/win_overview.rb
DELETED
data/gui/win_timelog_edit.rb
DELETED
@@ -1,153 +0,0 @@
|
|
1
|
-
class Openall_time_applet::Gui::Win_timelog_edit
|
2
|
-
attr_reader :args, :gui
|
3
|
-
|
4
|
-
def initialize(args)
|
5
|
-
@args = args
|
6
|
-
|
7
|
-
@gui = Gtk::Builder.new.add("../glade/win_timelog_edit.glade")
|
8
|
-
@gui.translate
|
9
|
-
@gui.connect_signals{|h| method(h)}
|
10
|
-
|
11
|
-
tasks_opts = [_("None")] + @args[:oata].ob.list(:Task, {"orderby" => "openall_uid"})
|
12
|
-
@gui["cbTask"].init(tasks_opts)
|
13
|
-
|
14
|
-
Knj::Gtk2::Cb.init(
|
15
|
-
"cb" => @gui["cbTimeType"],
|
16
|
-
"items" => {
|
17
|
-
"normal" => _("Normal"),
|
18
|
-
"overtime150" => sprintf(_("Overtime %s"), 150),
|
19
|
-
"overtime200" => sprintf(_("Overtime %s"), 200)
|
20
|
-
}
|
21
|
-
)
|
22
|
-
|
23
|
-
|
24
|
-
#Set up completion for description entry.
|
25
|
-
ec = Gtk::EntryCompletion.new
|
26
|
-
ec.model = Gtk::ListStore.new(String)
|
27
|
-
ec.text_column = 0
|
28
|
-
@gui["txtDescr"].completion = ec
|
29
|
-
|
30
|
-
added = {}
|
31
|
-
@args[:oata].ob.list(:Worktime, {"orderby" => "timestamp"}) do |worktime|
|
32
|
-
next if added.key?(worktime[:comment])
|
33
|
-
added[worktime[:comment]] = true
|
34
|
-
ec.model.append[0] = worktime[:comment]
|
35
|
-
end
|
36
|
-
|
37
|
-
@args[:oata].ob.list(:Timelog, {"orderby" => "descr"}) do |timelog|
|
38
|
-
next if added.key?(timelog[:descr])
|
39
|
-
added[timelog[:descr]] = true
|
40
|
-
ec.model.append[0] = timelog[:descr]
|
41
|
-
end
|
42
|
-
|
43
|
-
ec.signal_connect("match-selected") do |me, model, iter|
|
44
|
-
text = model.get_value(iter, 0)
|
45
|
-
me.entry.text = text
|
46
|
-
true
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
|
-
#We are editting a timelog - set widget-values.
|
51
|
-
@timelog = @args[:timelog]
|
52
|
-
|
53
|
-
if @timelog
|
54
|
-
@gui["txtDescr"].text = @timelog[:descr]
|
55
|
-
@gui["txtTime"].text = @timelog.time_as_human
|
56
|
-
@gui["txtTimeTransport"].text = @timelog.time_transport_as_human
|
57
|
-
@gui["txtTransportLength"].text = Knj::Locales.number_out(@timelog[:transportlength], 0)
|
58
|
-
@gui["txtTransportCosts"].text = Knj::Locales.number_out(@timelog[:transportcosts], 0)
|
59
|
-
@gui["txtTransportDescr"].text = @timelog[:transportdescription]
|
60
|
-
@gui["cbTask"].sel = @timelog.task if @timelog.task
|
61
|
-
@gui["cbShouldSync"].active = Knj::Strings.yn_str(@timelog[:sync_need], true, false)
|
62
|
-
@gui["cbTravelFixed"].active = Knj::Strings.yn_str(@timelog[:travelfixed], true, false)
|
63
|
-
@gui["cbWorkInternal"].active = Knj::Strings.yn_str(@timelog[:workinternal], true, false)
|
64
|
-
@gui["cbTimeType"].sel = @timelog[:timetype]
|
65
|
-
@gui["txtTimestamp"].text = Knj::Datet.in(@timelog[:timestamp]).out
|
66
|
-
else
|
67
|
-
@gui["btnRemove"].visible = false
|
68
|
-
@gui["txtTimestamp"].text = Knj::Datet.new.out
|
69
|
-
end
|
70
|
-
|
71
|
-
#Show the window.
|
72
|
-
@gui["window"].show
|
73
|
-
end
|
74
|
-
|
75
|
-
def on_btnSave_clicked(*args)
|
76
|
-
#Generate task-ID based on widget-value.
|
77
|
-
task = @gui["cbTask"].sel
|
78
|
-
if task.respond_to?(:is_knj?)
|
79
|
-
task_id = task.id
|
80
|
-
else
|
81
|
-
task_id = 0
|
82
|
-
end
|
83
|
-
|
84
|
-
#Get times as integers based on widget-values.
|
85
|
-
if @gui["txtTime"].text == ""
|
86
|
-
time_secs = 0
|
87
|
-
else
|
88
|
-
begin
|
89
|
-
time_secs = Knj::Strings.human_time_str_to_secs(@gui["txtTime"].text)
|
90
|
-
rescue => e
|
91
|
-
Knj::Gtk2.msgbox(_("You have entered an invalid time-format.") + "\n\n" + Knj::Errors.error_str(e))
|
92
|
-
return nil
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
if @gui["txtTimeTransport"].text == ""
|
97
|
-
time_transport_secs = 0
|
98
|
-
else
|
99
|
-
begin
|
100
|
-
time_transport_secs = Knj::Strings.human_time_str_to_secs(@gui["txtTimeTransport"].text)
|
101
|
-
rescue => e
|
102
|
-
Knj::Gtk2.msgbox(_("You have entered an invalid transport-time-format.") + "\n\n" + Knj::Errors.error_str(e))
|
103
|
-
return nil
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
begin
|
108
|
-
timestamp_dbstr = Knj::Datet.in(@gui["txtTimestamp"].text).dbstr
|
109
|
-
rescue
|
110
|
-
Knj::Gtk2.msgbox(_("You have entered an invalid timestamp."))
|
111
|
-
return nil
|
112
|
-
end
|
113
|
-
|
114
|
-
#Generate hash for updating dataabase.
|
115
|
-
save_hash = {
|
116
|
-
:descr => @gui["txtDescr"].text,
|
117
|
-
:timestamp => timestamp_dbstr,
|
118
|
-
:time => time_secs,
|
119
|
-
:timetype => @gui["cbTimeType"].sel,
|
120
|
-
:time_transport => time_transport_secs,
|
121
|
-
:transportdescription => @gui["txtTransportDescr"].text,
|
122
|
-
:transportlength => Knj::Locales.number_in(@gui["txtTransportLength"].text),
|
123
|
-
:transportcosts => Knj::Locales.number_in(@gui["txtTransportCosts"].text),
|
124
|
-
:task_id => task_id,
|
125
|
-
:sync_need => Knj::Strings.yn_str(@gui["cbShouldSync"].active?, 1, 0),
|
126
|
-
:workinternal => Knj::Strings.yn_str(@gui["cbWorkInternal"].active?, 1, 0),
|
127
|
-
:travelfixed => Knj::Strings.yn_str(@gui["cbTravelFixed"].active?, 1, 0)
|
128
|
-
}
|
129
|
-
|
130
|
-
#Update or add the timelog.
|
131
|
-
if @timelog
|
132
|
-
@timelog.update(save_hash)
|
133
|
-
else
|
134
|
-
@timelog = @args[:oata].ob.add(:Timelog, save_hash)
|
135
|
-
end
|
136
|
-
|
137
|
-
#Start tracking the current timelog if the checkbox has been checked.
|
138
|
-
if @gui["cbStartTracking"].active?
|
139
|
-
@args[:oata].timelog_active = @timelog
|
140
|
-
end
|
141
|
-
|
142
|
-
@gui["window"].destroy
|
143
|
-
end
|
144
|
-
|
145
|
-
def on_btnRemove_clicked(*args)
|
146
|
-
if Knj::Gtk2.msgbox(_("Do you want to remove this timelog? This will not delete the timelog on OpenAll."), "yesno") != "yes"
|
147
|
-
return nil
|
148
|
-
end
|
149
|
-
|
150
|
-
@args[:oata].ob.delete(@timelog)
|
151
|
-
@gui["window"].destroy
|
152
|
-
end
|
153
|
-
end
|