[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

rubyqt, popen problem in a log viewer

Bauduin Raphael

12/16/2004 9:39:00 PM

Hi,

I'm looking at Qtruby, trying to write a little log view app.
I'm basing the app on the p3 app from the tutorial found here:
http://developer.kde.org/language-bindings/ruby/kde3tutori...

I modify it like that:

hello = Qt::TextEdit.new( "", "", self)
hello.textFormat = Qt::LogText

setCentralWidget hello

Thread.new("/tmp/test") do |f|
tail = IO.popen("/usr/bin/tail -f #{f}","r")

while line = tail.gets
hello.append line.chomp
#hello.refresh
end
end


First problem: when I qui the app, the tail -f continues to run.
I also tried to put the while in a block passed to IO.popen, with the
same result. This then understandably results in the message

/usr/bin/tail: write error: Broken pipe
/usr/bin/tail: write error

in the terminal from which I started the app when a new line is appended
to the watched file.

I have also problems refreshing the widget when a new log line is
appended. If I uncomment hello.refresh after hello.append, only the
first line is displayed in the widget when I start the app, and when new
log lines are appended to the watched file, I get the broken pipe in the
terminal. When replacing hello.refresh by puts line.chomp, the program
works fine, except for the refrech problem.....

Thanks for your help.

Raph
6 Answers

nobu.nokada

12/17/2004 12:26:00 AM

0

Hi,

At Fri, 17 Dec 2004 06:42:13 +0900,
Bauduin Raphael wrote in [ruby-talk:123847]:
> I modify it like that:
>
> hello = Qt::TextEdit.new( "", "", self)
> hello.textFormat = Qt::LogText
>
> setCentralWidget hello
>
> Thread.new("/tmp/test") do |f|
begin
> tail = IO.popen("/usr/bin/tail -f #{f}","r")
>
> while line = tail.gets
> hello.append line.chomp
> #hello.refresh
> end
ensure
Process.kill("INT", tail.pid)
tail.close
end
> end

--
Nobu Nakada


Richard Dale

12/17/2004 1:37:00 AM

0

Bauduin Raphael wrote:

> Hi,
>
> I'm looking at Qtruby, trying to write a little log view app.
> I'm basing the app on the p3 app from the tutorial found here:
> http://developer.kde.org/language-bindings/ruby/kde3tutori...
>
> I modify it like that:
>
> hello = Qt::TextEdit.new( "", "", self)
> hello.textFormat = Qt::LogText
>
> setCentralWidget hello
>
> Thread.new("/tmp/test") do |f|
> tail = IO.popen("/usr/bin/tail -f #{f}","r")
>
> while line = tail.gets
> hello.append line.chomp
> #hello.refresh
> end
> end
>
>
> First problem: when I qui the app, the tail -f continues to run.
> I also tried to put the while in a block passed to IO.popen, with the
> same result. This then understandably results in the message
>
> /usr/bin/tail: write error: Broken pipe
> /usr/bin/tail: write error
>
> in the terminal from which I started the app when a new line is appended
> to the watched file.
>
> I have also problems refreshing the widget when a new log line is
> appended. If I uncomment hello.refresh after hello.append, only the
> first line is displayed in the widget when I start the app, and when new
> log lines are appended to the watched file, I get the broken pipe in the
> terminal. When replacing hello.refresh by puts line.chomp, the program
> works fine, except for the refrech problem.....

You could start 'tail' with a Qt::Process instead of popen(), as it ties in
with Qt signals/slots and shuts down the sub process on application exit:

@hello = Qt::TextEdit.new("", "", self)
@hello.textFormat = Qt::LogText

setCentralWidget(@hello)

@proc = Qt::Process.new(self) {
addArgument "/usr/bin/tail"
addArgument "-f"
addArgument "/tmp/test"
}

connect( @proc, SIGNAL('readyReadStdout()'),
self, SLOT('readFromStdout()') )
@proc.start
end

slots 'readFromStdout()'

def readFromStdout
lines = @proc.readStdout
@hello.append lines.to_s
end

-- Richard

Richard Dale

12/17/2004 2:58:00 AM

0

Richard Dale wrote:
> You could start 'tail' with a Qt::Process instead of popen(), as it ties
> in with Qt signals/slots

> and shuts down the sub process on application
> exit
Actually I'm wrong - Qt doesn't do this, you need to connect to the
'aboutToQuit()' application signal, and kill the 'tail' process on exit:

@proc = Qt::Process.new(self) {
addArgument "/usr/bin/tail"
addArgument "-f"
addArgument "/tmp/test"
}

connect( @proc, SIGNAL('readyReadStdout()'),
self, SLOT('readFromStdout()') )

connect( $kapp, SIGNAL('aboutToQuit()'),
self, SLOT('shutdown()') )
@proc.start
end

slots 'readFromStdout()', 'shutdown()'

def readFromStdout
lines = @proc.readStdout
@hello.append lines.to_s
end

def shutdown
@proc.kill
end

-- Richard

Bauduin Raphael

12/18/2004 1:31:00 PM

0

Hi,

Thanks for the tip about QProcess, I'll experiment with it later.
For the time being, I've implemented nobu nokada's suggestion.

I still have the problem refreshing the widget though....

With this code:

Thread.new("/tmp/test") do |f|
begin
tail = IO.popen("/usr/bin/tail -f #{f}","r")
while line = tail.gets
hello.append line.chomp
puts line.chomp
end

ensure
puts "killing #{tail.pid}"
Process.kill("INT", tail.pid)
tail.close
end
end

the while loops (updating the widget AND printing line in the terminal)
seems to be run only when activity occurs in the window (click, entering
window).

How comes the line is printed in the terminal only when activity occurs
in the window?

Thanks for your help

Raph



Richard Dale wrote:
> Richard Dale wrote:
>
>>You could start 'tail' with a Qt::Process instead of popen(), as it ties
>>in with Qt signals/slots
>
>
>>and shuts down the sub process on application
>>exit
>
> Actually I'm wrong - Qt doesn't do this, you need to connect to the
> 'aboutToQuit()' application signal, and kill the 'tail' process on exit:
>
> @proc = Qt::Process.new(self) {
> addArgument "/usr/bin/tail"
> addArgument "-f"
> addArgument "/tmp/test"
> }
>
> connect( @proc, SIGNAL('readyReadStdout()'),
> self, SLOT('readFromStdout()') )
>
> connect( $kapp, SIGNAL('aboutToQuit()'),
> self, SLOT('shutdown()') )
> @proc.start
> end
>
> slots 'readFromStdout()', 'shutdown()'
>
> def readFromStdout
> lines = @proc.readStdout
> @hello.append lines.to_s
> end
>
> def shutdown
> @proc.kill
> end
>
> -- Richard

Richard Dale

12/19/2004 12:46:00 PM

0

Bauduin Raphael wrote:

> Hi,
>
> Thanks for the tip about QProcess, I'll experiment with it later.
> For the time being, I've implemented nobu nokada's suggestion.
>
> I still have the problem refreshing the widget though....
>
> With this code:
>
> Thread.new("/tmp/test") do |f|
> begin
> tail = IO.popen("/usr/bin/tail -f #{f}","r")
> while line = tail.gets
> hello.append line.chomp
> puts line.chomp
> end
>
> ensure
> puts "killing #{tail.pid}"
> Process.kill("INT", tail.pid)
> tail.close
> end
> end
>
> the while loops (updating the widget AND printing line in the terminal)
> seems to be run only when activity occurs in the window (click, entering
> window).
>
> How comes the line is printed in the terminal only when activity occurs
> in the window?
Ruby threads aren't compatible with QtRuby - you have to always use the same
ruby thread to make Qt calls. Another approach would be to use a Qt::Timer
to periodically poll for input from tail:

?slots 'input()'
?
?def initialize()
? super()
? @timer = Qt::Timer.new
? connect(@timer, SIGNAL('timeout()'), SLOT('input()'))
? @timer.start(200)
?end

?def input
# Read from the pipe, append text to the Qt::TextEdit widget
?end

-- Richard

Alexander Kellett

12/19/2004 4:57:00 PM

0

or use qt::eventloop::processevents (something like that :P)
Alex

On Dec 19, 2004, at 1:47 PM, Richard Dale wrote:

> Bauduin Raphael wrote:
>
>> Hi,
>>
>> Thanks for the tip about QProcess, I'll experiment with it later.
>> For the time being, I've implemented nobu nokada's suggestion.
>>
>> I still have the problem refreshing the widget though....
>>
>> With this code:
>>
>> Thread.new("/tmp/test") do |f|
>> begin
>> tail = IO.popen("/usr/bin/tail -f #{f}","r")
>> while line = tail.gets
>> hello.append line.chomp
>> puts line.chomp
>> end
>>
>> ensure
>> puts "killing #{tail.pid}"
>> Process.kill("INT", tail.pid)
>> tail.close
>> end
>> end
>>
>> the while loops (updating the widget AND printing line in the
>> terminal)
>> seems to be run only when activity occurs in the window (click,
>> entering
>> window).
>>
>> How comes the line is printed in the terminal only when activity
>> occurs
>> in the window?
> Ruby threads aren't compatible with QtRuby - you have to always use
> the same
> ruby thread to make Qt calls. Another approach would be to use a
> Qt::Timer
> to periodically poll for input from tail:
>
>  slots 'input()'
>  
>  def initialize()
>   super()
>   @timer = Qt::Timer.new
>   connect(@timer, SIGNAL('timeout()'), SLOT('input()'))
>   @timer.start(200)
>  end
>
>  def input
> # Read from the pipe, append text to the Qt::TextEdit widget
>  end
>
> -- Richard
>