diff options
author | Tobi Oetiker <tobi@oetiker.ch> | 2008-06-05 17:36:43 +0200 |
---|---|---|
committer | Tobi Oetiker <tobi@oetiker.ch> | 2008-06-05 17:36:43 +0200 |
commit | f7c8c95ddc80c3b26f0d7978b776e02bc950a9fa (patch) | |
tree | 2f53d336c3bcaa9b6da3d041d35df181feb9b817 | |
parent | 6650ea2659e4817aedfe5e634afebfe487e83175 (diff) | |
download | smokeping-f7c8c95ddc80c3b26f0d7978b776e02bc950a9fa.tar.gz smokeping-f7c8c95ddc80c3b26f0d7978b776e02bc950a9fa.tar.xz |
improved handling of non responsive hosts
routes flapping
hosts with multiple ip addresses
-rw-r--r-- | qooxdoo/source/class/Tr/Application.js | 3 | ||||
-rw-r--r-- | qooxdoo/source/class/Tr/ui/ActionButton.js | 44 | ||||
-rw-r--r-- | qooxdoo/source/class/Tr/ui/TraceTable.js | 83 | ||||
-rw-r--r-- | qooxdoo/source/perl/Qooxdoo/Services/Tr.pm | 48 | ||||
-rw-r--r-- | qooxdoo/source/translation/C.po | 22 | ||||
-rw-r--r-- | qooxdoo/source/translation/de.po | 22 | ||||
-rw-r--r-- | qooxdoo/source/translation/en.po | 22 | ||||
-rw-r--r-- | qooxdoo/source/translation/fr.po | 22 | ||||
-rw-r--r-- | qooxdoo/source/translation/messages.pot | 22 |
9 files changed, 182 insertions, 106 deletions
diff --git a/qooxdoo/source/class/Tr/Application.js b/qooxdoo/source/class/Tr/Application.js index bcac0d9..5c6298b 100644 --- a/qooxdoo/source/class/Tr/Application.js +++ b/qooxdoo/source/class/Tr/Application.js @@ -53,8 +53,9 @@ qx.Class.define('Tr.Application', base_layout.add(top); var trace = new Tr.ui.TraceTable(); base_layout.add(trace); + base_layout.add(new Tr.ui.Footer(this.tr("SmokeTrace is part of the SmokePing suite created by Tobi Oetiker, Copyright 2008."),'http://oss.oetiker.ch/smokeping')); }, - + close : function(e) { this.base(arguments); diff --git a/qooxdoo/source/class/Tr/ui/ActionButton.js b/qooxdoo/source/class/Tr/ui/ActionButton.js index f710df9..ae04efb 100644 --- a/qooxdoo/source/class/Tr/ui/ActionButton.js +++ b/qooxdoo/source/class/Tr/ui/ActionButton.js @@ -8,7 +8,7 @@ qx.Class.define('Tr.ui.ActionButton', { - extend: qx.ui.layout.HorizontalBoxLayout, + extend: qx.ui.layout.VerticalBoxLayout, /* ***************************************************************************** @@ -22,13 +22,19 @@ qx.Class.define('Tr.ui.ActionButton', this.set({ height: 'auto', width: 'auto', + horizontalChildrenAlign: 'left' + }); + var hbox = new qx.ui.layout.HorizontalBoxLayout; + hbox.set({ + height: 'auto', + width: 'auto', verticalChildrenAlign: 'middle' }); var lab1 = new qx.ui.basic.Label(this.tr("Host")); lab1.set({ paddingRight: 6 }); - this.add(lab1); + hbox.add(lab1); var host = new qx.ui.form.TextField(); host.set({ width: 200, @@ -36,20 +42,20 @@ qx.Class.define('Tr.ui.ActionButton', border: 'dark-shadow', padding: 1 }); - this.add(host); + hbox.add(host); this.__host = host; var lab2 = new qx.ui.basic.Label(this.tr("Delay")); lab2.set({ paddingRight: 6, paddingLeft: 12 }); - this.add(lab2); + hbox.add(lab2); var delay = new qx.ui.form.Spinner(1,2,60); delay.set({ border: 'dark-shadow', width: 45 }); - this.add(delay); + hbox.add(delay); this.__delay = delay; var lab3 = new qx.ui.basic.Label(this.tr("Rounds")); @@ -57,13 +63,13 @@ qx.Class.define('Tr.ui.ActionButton', paddingRight: 6, paddingLeft: 12 }); - this.add(lab3); + hbox.add(lab3); var rounds = new qx.ui.form.Spinner(1,20,200); rounds.set({ border: 'dark-shadow', width: 45 }); - this.add(rounds); + hbox.add(rounds); this.__rounds = rounds; var button = new qx.ui.form.Button(''); @@ -75,7 +81,21 @@ qx.Class.define('Tr.ui.ActionButton', border: 'dark-shadow', padding: 2 }); - this.add(button); + hbox.add(button); + this.add(hbox); + var info = new qx.ui.basic.Atom(); + info.set({ + marginTop: 3, + padding: 3, + textColor: 'red', + width: '100%', + height: 'auto', + backgroundColor: '#f0f0f0', + visibility: false + }); + qx.event.message.Bus.subscribe('tr.info',this.__set_info,this); + this.add(info); + this.__info = info; qx.event.message.Bus.subscribe('tr.status',this.__set_status,this); qx.event.message.Bus.dispatch('tr.status','stopped'); @@ -114,6 +134,12 @@ qx.Class.define('Tr.ui.ActionButton', }, members: { + __set_info: function(e){ + this.__info.set({ + label: e.getData(), + visibility: true + }); + }, __set_status: function(m){ var host = this.__host; var rounds = this.__rounds; @@ -124,6 +150,8 @@ qx.Class.define('Tr.ui.ActionButton', case 'starting': if (getUserData('action') == 'go') { setLabel(this.tr("Starting")); + this.__info.setVisibility(false); + border: 'dark-shadow' setEnabled(false); host.setEnabled(false); rounds.setEnabled(false); diff --git a/qooxdoo/source/class/Tr/ui/TraceTable.js b/qooxdoo/source/class/Tr/ui/TraceTable.js index 5141884..3330740 100644 --- a/qooxdoo/source/class/Tr/ui/TraceTable.js +++ b/qooxdoo/source/class/Tr/ui/TraceTable.js @@ -42,7 +42,7 @@ qx.Class.define('Tr.ui.TraceTable', var tcm = this.getTableColumnModel(); this.__tcm = tcm; - //tcm.setDataCellRenderer(0, new Tr.ui.Cellrenderer(2)); + tcm.setDataCellRenderer(0, new Tr.ui.Cellrenderer(1)); tcm.setDataCellRenderer(3, new Tr.ui.Cellrenderer(0,' %')); tcm.setDataCellRenderer(4, new Tr.ui.Cellrenderer(0)); @@ -75,6 +75,14 @@ qx.Class.define('Tr.ui.TraceTable', __make_empty_row: function (){ return ([undefined,undefined,undefined,0,0,undefined,undefined,undefined,undefined,undefined,0,0,0]); }, + __stop_table: function (){ + var tableModel = this.__tableModel; + for (var i=0;i<10;i++){ + tableModel.setColumnSortable(i,true); + } + qx.event.message.Bus.dispatch('tr.status','stopped'); + this.__handle = undefined; + }, __handle_tr: function(m){ var self = this; var f_hop = 0,f_host=1,f_ip=2,f_loss=3,f_snt=4,f_last=5,f_avg=6,f_best=7,f_worst=8,f_stdev=9,f_cnt=10,f_sum=11,f_sqsum=12; @@ -93,49 +101,55 @@ qx.Class.define('Tr.ui.TraceTable', sleep = 0; var hop = retval['output'][i][0]; if (hop == 'SLEEP'){ - sleep = self.__delay * 1000; + sleep = retval['output'][i][1]; continue; - } + } + else if (hop == 'INFO'){ + qx.event.message.Bus.dispatch('tr.info',retval['output'][i][1]); + continue; + } var host = retval['output'][i][1]; var ip = retval['output'][i][2]; var value = retval['output'][i][3]; var ii = 0; var max = data.length; - while ( ii < max - && ( Math.floor(data[ii][0]) < hop - || ( Math.floor(data[ii][0]) == hop && data[ii][1] != host) - ) - ){ + while (true){ + if ( ii == max ) break; + if ( Math.floor(data[ii][0]) > hop) break; + if ( Math.floor(data[ii][0]) == hop ){ + if ( ip == undefined ) break; + if ( ip == data[ii][2] ) break; + } ii++; } - if (ii == max || ( Math.floor(data[ii][0]) == hop && data[ii][1] != host) ){ - if (ii < max){ - hop = data[ii][0] + 0.1; + if (ii == max || Math.floor(data[ii][0]) > hop ){ + if (ii > 0 && Math.floor(data[ii-1][0]) == hop ){ + hop = data[ii-1][0] + 0.1; } data.splice(ii,0,self.__make_empty_row()); data[ii][0] = hop; } var drow = data[ii]; - if (drow[f_host] == undefined){ + if (drow[f_host] == undefined && host != undefined){ drow[f_host] = host; } - if (drow[f_ip] == undefined){ + if (drow[f_ip] == undefined && ip != undefined){ drow[f_ip] = ip; } drow[f_snt]++; drow[f_last] = value; - var best = drow[f_best]; - if (best == undefined || best > value){ - drow[f_best] = value; - } - var worst = drow[f_worst]; - if (worst == undefined || worst < value){ - drow[f_worst] = value; - } if (value != undefined){ + var best = drow[f_best]; + if (best == undefined || best > value){ + drow[f_best] = value; + } + var worst = drow[f_worst]; + if (worst == undefined || worst < value){ + drow[f_worst] = value; + } drow[f_sum] += value; var sum = drow[f_sum]; drow[f_cnt] ++; @@ -154,29 +168,22 @@ qx.Class.define('Tr.ui.TraceTable', fill_table,'run_tr',{ handle: retval['handle'], point: retval['point']})}; qx.client.Timer.once(next_round,self,sleep); - } else - { - for (var i=0;i<10;i++){ - tableModel.setColumnSortable(i,true); - } - qx.event.message.Bus.dispatch('tr.status','stopped'); - self.__handle = undefined; + } + else { + self.__stop_table(); } } else { alert(exc); - if (self.__handle){ - self.__handle = undefined; - } - for (var i=0;i<10;i++){ - self.__tableModel.setColumnSortable(i,true); - } - qx.event.message.Bus.dispatch('tr.status','stopped'); + self.__stop_table(); } }; - var handle_returns = function (data,exc,id){ - if (exc != null){ + var stop_handler = function (data,exc,id){ + if (exc == null){ + qx.event.message.Bus.dispatch('tr.status','stopped'); + } + else { alert(exc); } }; @@ -185,7 +192,7 @@ qx.Class.define('Tr.ui.TraceTable', switch(cmd['action']){ case 'stop': qx.event.message.Bus.dispatch('tr.status','stopping'); - Tr.Server.getInstance().callAsync(handle_returns,'stop_tr',this.__handle); + Tr.Server.getInstance().callAsync(stop_handler,'stop_tr',this.__handle); break; case 'go': this.__data = []; diff --git a/qooxdoo/source/perl/Qooxdoo/Services/Tr.pm b/qooxdoo/source/perl/Qooxdoo/Services/Tr.pm index 4d6f54b..0cf88b3 100644 --- a/qooxdoo/source/perl/Qooxdoo/Services/Tr.pm +++ b/qooxdoo/source/perl/Qooxdoo/Services/Tr.pm @@ -2,7 +2,7 @@ package Qooxdoo::Services::Tr; use strict; use POSIX qw(setsid :sys_wait_h); use Time::HiRes qw(usleep); - +use Socket; sub GetAccessibility { return "public"; } @@ -28,9 +28,13 @@ sub launch { setsid or die "Can't start a new session: $!"; open STDERR, '>&STDOUT' or die "Can't dup stdout: $!"; for (my $i = 0; $i<$rounds;$i++){ - system "traceroute","-I","-q","1",$host; -# print "SLEEPING\n"; - sleep $delay; + my $start = time; + system "traceroute","-I","-q","1",$host; + my $wait = $delay - (time - $start); + if ($wait > 0){ + print "SLEEP $wait\n"; + sleep $wait; + } } exit 0; } @@ -55,9 +59,12 @@ sub method_stop_tr { return $handle if ref $handle; my $data = "/tmp/tr_session.".$handle; if (-r $data){ - warn "Sending kill $handle"; - kill('KILL',$handle); + warn "Sending kill $handle"; + if (kill('KILL',$handle)){ + waitpid($handle,0); + } } + return 'ok'; } sub method_run_tr @@ -66,12 +73,21 @@ sub method_run_tr my $arg = shift; my $handle = get_number($error,$arg->{handle}); my $point = get_number($error,$arg->{point}); + my @array; if ($arg->{host}){ + my $host = $arg->{host}; + if ( my @addresses = gethostbyname($host) ){ + @addresses = map { inet_ntoa($_) } @addresses[4 .. $#addresses]; + if ($#addresses > 1){ + $host = $addresses[rand($#addresses)]; + push @array, ['INFO',"Found $#addresses addresses for $arg->{host}. Using $host."]; + } + } my $delay = get_number($error,$arg->{delay}); return $delay if ref $delay; my $rounds = get_number($error,$arg->{rounds}); return $rounds if ref $rounds; - $handle = launch ($error,$rounds,$delay,$arg->{host}); + $handle = launch ($error,$rounds,$delay,$host); $point = 0; } return $point if ref $point; @@ -92,33 +108,27 @@ sub method_run_tr $rounds ++; } while ($again and $point >= $size); if (seek $fh, $point,0){ - my @array; while (<$fh>){ waitpid($handle,WNOHANG); /^traceroute to/ && next; - if (/unknown host/){ - $error->set_error(108,"Unknown hostname."); - return $error; - } last unless /\n$/; # stop when we find an incomplete line + chomp; if (/^\s*(\d+)\s+(\S+)\s+\((\S+?)\)\s+(\S+)\s+ms/){ my ($hop,$host,$ip,$value) = ($1,$2,$3,$4); $value = undef unless $value =~ /^\d+(\.\d+)?$/; push @array, [$hop,$host,$ip,$value]; - $point = tell($fh); } elsif (/^\s*(\d+)\s+\*/){ push @array, [$1,undef,undef,undef]; - $point = tell($fh); } - elsif (/^SLEEPING/){ - push @array, ['SLEEPING']; - $point = tell($fh); + elsif (/^SLEEP\s+(\d+)/){ + push @array, ['SLEEP',$1]; } else { - $error->set_error(107,"ERROR: $_. See $data for more information."); - return $error; + s/traceroute:\s*//g; + push @array, ['INFO',$_]; } + $point = tell($fh); }; close $fh; unlink $data unless $again; diff --git a/qooxdoo/source/translation/C.po b/qooxdoo/source/translation/C.po index 1cc935f..5d20a3b 100644 --- a/qooxdoo/source/translation/C.po +++ b/qooxdoo/source/translation/C.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-06-05 01:21+0200\n" +"POT-Creation-Date: 2008-06-05 17:17+0200\n" "PO-Revision-Date: 2007-10-19 09:30+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -19,31 +19,37 @@ msgstr "" msgid "SmokeTraceroute" msgstr "" -#: source/class/Tr/ui/ActionButton.js:27 source/class/Tr/ui/TraceTable.js:24 +#: source/class/Tr/Application.js:56 +msgid "" +"SmokeTrace is part of the SmokePing suite created by Tobi Oetiker, Copyright " +"2008." +msgstr "" + +#: source/class/Tr/ui/ActionButton.js:33 source/class/Tr/ui/TraceTable.js:24 msgid "Host" msgstr "" -#: source/class/Tr/ui/ActionButton.js:41 +#: source/class/Tr/ui/ActionButton.js:47 msgid "Delay" msgstr "" -#: source/class/Tr/ui/ActionButton.js:55 +#: source/class/Tr/ui/ActionButton.js:61 msgid "Rounds" msgstr "" -#: source/class/Tr/ui/ActionButton.js:126 +#: source/class/Tr/ui/ActionButton.js:152 msgid "Starting" msgstr "" -#: source/class/Tr/ui/ActionButton.js:135 +#: source/class/Tr/ui/ActionButton.js:163 msgid "Stopping" msgstr "" -#: source/class/Tr/ui/ActionButton.js:144 +#: source/class/Tr/ui/ActionButton.js:172 msgid "Go" msgstr "" -#: source/class/Tr/ui/ActionButton.js:152 +#: source/class/Tr/ui/ActionButton.js:180 msgid "Stop" msgstr "" diff --git a/qooxdoo/source/translation/de.po b/qooxdoo/source/translation/de.po index 55270ce..a09deb1 100644 --- a/qooxdoo/source/translation/de.po +++ b/qooxdoo/source/translation/de.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: MTR-AJAX-Frontend 1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-06-05 01:21+0200\n" +"POT-Creation-Date: 2008-06-05 17:17+0200\n" "PO-Revision-Date: 2008-05-31 08:50+0200\n" "Last-Translator: oetiker <(null)>\n" "Language-Team: English <en@li.org>\n" @@ -19,33 +19,39 @@ msgstr "" msgid "SmokeTraceroute" msgstr "" -#: source/class/Tr/ui/ActionButton.js:27 source/class/Tr/ui/TraceTable.js:24 +#: source/class/Tr/Application.js:56 +msgid "" +"SmokeTrace is part of the SmokePing suite created by Tobi Oetiker, Copyright " +"2008." +msgstr "" + +#: source/class/Tr/ui/ActionButton.js:33 source/class/Tr/ui/TraceTable.js:24 msgid "Host" msgstr "Host" -#: source/class/Tr/ui/ActionButton.js:41 +#: source/class/Tr/ui/ActionButton.js:47 msgid "Delay" msgstr "Abstand" -#: source/class/Tr/ui/ActionButton.js:55 +#: source/class/Tr/ui/ActionButton.js:61 msgid "Rounds" msgstr "Runden" -#: source/class/Tr/ui/ActionButton.js:126 +#: source/class/Tr/ui/ActionButton.js:152 #, fuzzy msgid "Starting" msgstr "Start" -#: source/class/Tr/ui/ActionButton.js:135 +#: source/class/Tr/ui/ActionButton.js:163 #, fuzzy msgid "Stopping" msgstr "Stop" -#: source/class/Tr/ui/ActionButton.js:144 +#: source/class/Tr/ui/ActionButton.js:172 msgid "Go" msgstr "Start" -#: source/class/Tr/ui/ActionButton.js:152 +#: source/class/Tr/ui/ActionButton.js:180 msgid "Stop" msgstr "Stop" diff --git a/qooxdoo/source/translation/en.po b/qooxdoo/source/translation/en.po index efc74a7..9d989d3 100644 --- a/qooxdoo/source/translation/en.po +++ b/qooxdoo/source/translation/en.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-06-05 01:21+0200\n" +"POT-Creation-Date: 2008-06-05 17:17+0200\n" "PO-Revision-Date: 2007-10-26 23:25+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -20,32 +20,38 @@ msgstr "" msgid "SmokeTraceroute" msgstr "" -#: source/class/Tr/ui/ActionButton.js:27 source/class/Tr/ui/TraceTable.js:24 +#: source/class/Tr/Application.js:56 +msgid "" +"SmokeTrace is part of the SmokePing suite created by Tobi Oetiker, Copyright " +"2008." +msgstr "" + +#: source/class/Tr/ui/ActionButton.js:33 source/class/Tr/ui/TraceTable.js:24 msgid "Host" msgstr "" -#: source/class/Tr/ui/ActionButton.js:41 +#: source/class/Tr/ui/ActionButton.js:47 msgid "Delay" msgstr "" -#: source/class/Tr/ui/ActionButton.js:55 +#: source/class/Tr/ui/ActionButton.js:61 msgid "Rounds" msgstr "" -#: source/class/Tr/ui/ActionButton.js:126 +#: source/class/Tr/ui/ActionButton.js:152 #, fuzzy msgid "Starting" msgstr "Start" -#: source/class/Tr/ui/ActionButton.js:135 +#: source/class/Tr/ui/ActionButton.js:163 msgid "Stopping" msgstr "" -#: source/class/Tr/ui/ActionButton.js:144 +#: source/class/Tr/ui/ActionButton.js:172 msgid "Go" msgstr "" -#: source/class/Tr/ui/ActionButton.js:152 +#: source/class/Tr/ui/ActionButton.js:180 msgid "Stop" msgstr "" diff --git a/qooxdoo/source/translation/fr.po b/qooxdoo/source/translation/fr.po index d6e7d86..89fac2a 100644 --- a/qooxdoo/source/translation/fr.po +++ b/qooxdoo/source/translation/fr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-06-05 01:21+0200\n" +"POT-Creation-Date: 2008-06-05 17:17+0200\n" "PO-Revision-Date: 2007-10-19 09:30+0200\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -20,31 +20,37 @@ msgstr "" msgid "SmokeTraceroute" msgstr "" -#: source/class/Tr/ui/ActionButton.js:27 source/class/Tr/ui/TraceTable.js:24 +#: source/class/Tr/Application.js:56 +msgid "" +"SmokeTrace is part of the SmokePing suite created by Tobi Oetiker, Copyright " +"2008." +msgstr "" + +#: source/class/Tr/ui/ActionButton.js:33 source/class/Tr/ui/TraceTable.js:24 msgid "Host" msgstr "" -#: source/class/Tr/ui/ActionButton.js:41 +#: source/class/Tr/ui/ActionButton.js:47 msgid "Delay" msgstr "" -#: source/class/Tr/ui/ActionButton.js:55 +#: source/class/Tr/ui/ActionButton.js:61 msgid "Rounds" msgstr "" -#: source/class/Tr/ui/ActionButton.js:126 +#: source/class/Tr/ui/ActionButton.js:152 msgid "Starting" msgstr "" -#: source/class/Tr/ui/ActionButton.js:135 +#: source/class/Tr/ui/ActionButton.js:163 msgid "Stopping" msgstr "" -#: source/class/Tr/ui/ActionButton.js:144 +#: source/class/Tr/ui/ActionButton.js:172 msgid "Go" msgstr "" -#: source/class/Tr/ui/ActionButton.js:152 +#: source/class/Tr/ui/ActionButton.js:180 msgid "Stop" msgstr "" diff --git a/qooxdoo/source/translation/messages.pot b/qooxdoo/source/translation/messages.pot index 3937747..a99dfc3 100644 --- a/qooxdoo/source/translation/messages.pot +++ b/qooxdoo/source/translation/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-06-05 08:36+0200\n" +"POT-Creation-Date: 2008-06-05 17:20+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -20,31 +20,37 @@ msgstr "" msgid "SmokeTraceroute" msgstr "" -#: source/class/Tr/ui/ActionButton.js:27 source/class/Tr/ui/TraceTable.js:24 +#: source/class/Tr/Application.js:56 +msgid "" +"SmokeTrace is part of the SmokePing suite created by Tobi Oetiker, Copyright " +"2008." +msgstr "" + +#: source/class/Tr/ui/ActionButton.js:33 source/class/Tr/ui/TraceTable.js:24 msgid "Host" msgstr "" -#: source/class/Tr/ui/ActionButton.js:41 +#: source/class/Tr/ui/ActionButton.js:47 msgid "Delay" msgstr "" -#: source/class/Tr/ui/ActionButton.js:55 +#: source/class/Tr/ui/ActionButton.js:61 msgid "Rounds" msgstr "" -#: source/class/Tr/ui/ActionButton.js:126 +#: source/class/Tr/ui/ActionButton.js:152 msgid "Starting" msgstr "" -#: source/class/Tr/ui/ActionButton.js:135 +#: source/class/Tr/ui/ActionButton.js:163 msgid "Stopping" msgstr "" -#: source/class/Tr/ui/ActionButton.js:144 +#: source/class/Tr/ui/ActionButton.js:172 msgid "Go" msgstr "" -#: source/class/Tr/ui/ActionButton.js:152 +#: source/class/Tr/ui/ActionButton.js:180 msgid "Stop" msgstr "" |