rubyqt, popen problem in a log viewer

B

Bauduin Raphael

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/kde3tutorial/p3.html

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
 
N

nobu.nokada

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
 
R

Richard Dale

Bauduin said:
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/kde3tutorial/p3.html

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
 
R

Richard Dale

Richard said:
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
 
B

Bauduin Raphael

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
 
R

Richard Dale

Bauduin said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top