Qt Threading?

G

gregarican

I have an app that I wrote using Ruby-Qt2. The main application is
fine, but I want to add something to it. I want a listener thread that
waits for incoming signals. The thread would need to operate as a loop.
For my example I just made a basic closed iterator to test things out.

Here is a sample:
-----------------

require "qt2"
include Qt2
require "applicationWindow" # a derived Qt class I made

listener=Thread.new {
puts "this is a sample of my listener thread!\n"
10.times do |i|
sleep 1
puts "#{i} second(s)...\n"
end
}

qtApp = Thread.new {
a = QApplication.new([$0]+ARGV)
mw = ApplicationWindow.new
mw.setCaption( QString.new("Qt App") )
mw.show
a.exec
}


listener.join
qtApp.join


------------------

The problem is that the threads don't seem to work independently. The
listener thread won't advance until the Qt application has processed a
couple of events. So the seconds don't count up in real-time. This
takes place on a Win32 platform, so I don't think I can use a fork
method to split things off independently.

Any suggestions on how my listening thread can work independently on my
Win32 platform? I have read about the QThread object, but am not sure
that this is the way to go...
 
G

gregarican

gregarican said:
The problem is that the threads don't seem to work independently. The
listener thread won't advance until the Qt application has processed a
couple of events. So the seconds don't count up in real-time. This
takes place on a Win32 platform, so I don't think I can use a fork
method to split things off independently.


I did stumble across -->
http://lists.trolltech.com/qt-interest/1997-06/thread00137-0.html,
which details how to implement QSocketNotify. I am assume this might be
the way to go?
 
R

Richard Dale

Ruby doesn't use native threads, and so as far as Qt is concerned you have a
single threaded application. Only when the Qt runtime calls say a ruby slot
in your code, will ruby be able to schedule the background thread to run.
I did stumble across -->
http://lists.trolltech.com/qt-interest/1997-06/thread00137-0.html,
which details how to implement QSocketNotify. I am assume this might be
the way to go?
Yes, it is. That way you don't need an extra thread, and you can detect any
input on the socket as part of the normal Qt event loop. But you didn't
describe quite what you wanted to monitor in your original post, I didn't
know what you meant by 'incoming signals'.

-- Richard
 
G

gregarican

Richard said:
Yes, it is. That way you don't need an extra thread, and you can detect any
input on the socket as part of the normal Qt event loop. But you didn't
describe quite what you wanted to monitor in your original post, I didn't
know what you meant by 'incoming signals'.

I have a CRM application that I've written. And I am looking to add CTI
screen pops coming from alerting phone calls. This is based off my
recent RubyPhone addition to the RubyForge projects. I want the caller
ID to be pushed into the CRM application's customer lookup window. My
CTI thread is just a loop that listens for the CTI caller ID
information.

Like this:
------------------------

require "tsapi"

screenPop=Thread.new {
puts "screen pop thread started!\n"
tsession=Tsapi.new("555","AVAYA#MAGIX#CSTA#MERLIN-CTI", "username",
"password", "CTI Test")
puts "tsession is #{tsession}.\n"

# this represents the call ID and caller ID of the incoming caller
caller = 0
callingNum= 0

# this represents the result set of the contact database lookup
contactData = []

puts "trying to invoke tsession.open()...\n"
results=tsession.open
puts "tsession open() returned #{results}.\n"
sleep 1

puts "trying to invoke tsession.monitorOn()...\n"
results=tsession.monitorOn(CF_DELIVERED, 0, 0, 0)
puts "tsession monitorOn() returned #{results}.\n"
sleep 1

loop do
sleep 1
if tsession.ringing? == true
caller=tsession.callIdMon
callingNum=tsession.callDevIdMon
puts "alerting call #{caller} from #{callingNum}.\n"
# retrieve the customer contact data associated with the incoming
calling number
c = XMLRPC::Client.new("10.0.0.200", "/RPC2", 8888)
contactData = c.call("crm.getContactScreenPop", "#{callingNum}")
if contactData == 1
@displayName, @compName, @lastName, @middleName, @firstName,
@street, @city, @state, @zip, @comments, @custNum, @birthday,
@anniversary, @spouseName, @homeCity, @homeZip, @homeState,
@homeStreet, @homeFax, @homePhone, @busFax, @busPhone, @cellPhone = ""
else
@displayName = contactData[0]
@compName = contactData[1]
@lastName = contactData[2]
@middleName = contactData[3]
@firstName = contactData[4]
@street = contactData[5]
@city = contactData[6]
@state = contactData[7]
@zip = contactData[8]
@comments = contactData[9]
@custNum = contactData[10]
@birthday = contactData[11]
@anniversary = contactData[12]
@spouseName = contactData[13]
@homeCity = contactData[14]
@homeZip = contactData[15]
@homeState = contactData[16]
@homeStreet = contactData[17]
@homeFax = contactData[18]
@homePhone = contactData[19]
@busFax = contactData[20]
@busPhone = contactData[21]
@cellPhone = contactData[22]

puts "Contact data:\n"
puts "-------------\n"
puts "Full Name: #{@displayName}\n"
puts "Street: #{@street}\n"
puts "City: #{@city}\n"
puts "State: #{@state}\n"
puts "ZIP: #{@zip}\n"
puts "Home Phone: #{@homePhone}\n"
puts "Bus. Phone: #{@busPhone}\n"
puts "Cell Phone: #{@cellPhone}\n"
puts "-------------------------\n"
puts "Comments: #{@comments}\n"
end
sleep 1
end
end
}
 
R

Richard Dale

gregarican said:
I have a CRM application that I've written. And I am looking to add CTI
screen pops coming from alerting phone calls. This is based off my
recent RubyPhone addition to the RubyForge projects. I want the caller
ID to be pushed into the CRM application's customer lookup window. My
CTI thread is just a loop that listens for the CTI caller ID
information.
You could use QSocketNotifier if there is something on a socket. You have:

if tsession.ringing? == true

As the condition controlling the loop (btw you don't need '== true' test).
If you can access the underlying socket, you can use QSocketNotifier.

Another way would be to set a QTimer to call a slot in your
ApplicationWindow class once a second. The slot doesn't have to actually do
anything, but it would give the background thread loop below a chance to
run.

-- Richard
Like this:
------------------------

require "tsapi"

screenPop=Thread.new {
puts "screen pop thread started!\n"
tsession=Tsapi.new("555","AVAYA#MAGIX#CSTA#MERLIN-CTI", "username",
"password", "CTI Test")
puts "tsession is #{tsession}.\n"

# this represents the call ID and caller ID of the incoming caller
caller = 0
callingNum= 0

# this represents the result set of the contact database lookup
contactData = []

puts "trying to invoke tsession.open()...\n"
results=tsession.open
puts "tsession open() returned #{results}.\n"
sleep 1

puts "trying to invoke tsession.monitorOn()...\n"
results=tsession.monitorOn(CF_DELIVERED, 0, 0, 0)
puts "tsession monitorOn() returned #{results}.\n"
sleep 1

loop do
sleep 1
if tsession.ringing? == true
caller=tsession.callIdMon
callingNum=tsession.callDevIdMon
puts "alerting call #{caller} from #{callingNum}.\n"
# retrieve the customer contact data associated with the incoming
calling number
c = XMLRPC::Client.new("10.0.0.200", "/RPC2", 8888)
contactData = c.call("crm.getContactScreenPop", "#{callingNum}")
if contactData == 1
@displayName, @compName, @lastName, @middleName, @firstName,
@street, @city, @state, @zip, @comments, @custNum, @birthday,
@anniversary, @spouseName, @homeCity, @homeZip, @homeState,
@homeStreet, @homeFax, @homePhone, @busFax, @busPhone, @cellPhone = ""
else
@displayName = contactData[0]
@compName = contactData[1]
@lastName = contactData[2]
@middleName = contactData[3]
@firstName = contactData[4]
@street = contactData[5]
@city = contactData[6]
@state = contactData[7]
@zip = contactData[8]
@comments = contactData[9]
@custNum = contactData[10]
@birthday = contactData[11]
@anniversary = contactData[12]
@spouseName = contactData[13]
@homeCity = contactData[14]
@homeZip = contactData[15]
@homeState = contactData[16]
@homeStreet = contactData[17]
@homeFax = contactData[18]
@homePhone = contactData[19]
@busFax = contactData[20]
@busPhone = contactData[21]
@cellPhone = contactData[22]

puts "Contact data:\n"
puts "-------------\n"
puts "Full Name: #{@displayName}\n"
puts "Street: #{@street}\n"
puts "City: #{@city}\n"
puts "State: #{@state}\n"
puts "ZIP: #{@zip}\n"
puts "Home Phone: #{@homePhone}\n"
puts "Bus. Phone: #{@busPhone}\n"
puts "Cell Phone: #{@cellPhone}\n"
puts "-------------------------\n"
puts "Comments: #{@comments}\n"
end
sleep 1
end
end
}
 
G

gregarican

Richard said:
Another way would be to set a QTimer to call a slot in your
ApplicationWindow class once a second. The slot doesn't have to actually do
anything, but it would give the background thread loop below a chance to
run.

The QTimer works like a champ. This is a great solution. I just need to
read up on the docs some more to ensure
that the QTimer gets killed off when the QApplication exits. Now when I
exit the GUI the QTimer thread DOS box stays on the Windows taskbar.
Other than that this was a quick fix. It's cool watching my caller ID
screen pops feed into my CRM application. Thanks for your tip!
 

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

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,242
Latest member
KendrickKo

Latest Threads

Top