The Bluetooth Chat example shows how to use the Qt Bluetooth API to communicate with another application on a remote device using Bluetooth.
Void VideoPlayer:: load ( const Phonon::MediaSource & source) slot Starts pre-loading the media data from the specified source and filling audio buffers in the backend. When there's already a media playing (or paused) it will be stopped (the finished signal will not be emitted). Void QCompleter:: activated ( const QModelIndex & index) signal This signal is sent when an item in the popup is activated by the user. (by clicking or pressing return). The item's index in the completionModel is given. Void QCompleter:: complete ( const QRect & rect = QRect ) slot. signal void QTableWidget:: cellActivated (int row, int column) This signal is emitted when the cell specified by row and column has been activated. This function was introduced in Qt 4.1. signal void QTableWidget:: cellChanged (int row, int column) This signal is emitted whenever the data of the item in the cell specified by row and column.
The Bluetooth Chat example implements a simple chat program between multiple parties. The application always acts as both a server and a client eliminating the need to determine who should connect to whom.
To run the example from Qt Creator, open the Welcome mode and select the example from Examples. For more information, visit Building and Running an Example.
The chat server is implemented by the ChatServer class. The ChatServer class is declared as:
The first thing the chat server needs to do is create an instance of QRfcommServer to listen for incoming Bluetooth connections. Our clientConnected() slot will be called whenever a new connection is created.
The chat server is only useful if others know that it is there. To enable other devices to discover it, a record describing the service needs to be published in the systems SDP (Service Discovery Protocol) database. The QBluetoothServiceInfo class encapsulates a service record.
We will publish a service record that contains some textural descriptions of the services, a UUID that uniquely identifies the service, the discoverability attribute, and connection parameters.
The textural description of the service is stored in the ServiceName, ServiceDescription, and ServiceProvider attributes.
Bluetooth uses UUIDs as unique identifiers. The chat service uses a randomly generated UUID.
A Bluetooth service is only discoverable if it is in the PublicBrowseGroup.
The ProtocolDescriptorList attribute is used to publish the connection parameters that the remote device requires to connect to our service. Here we specify that the Rfcomm protocol is used and set the port number to the port that our rfcommServer instance is listening to.
Finally, we register the service record with the system.
As mentioned earlier, incoming connections are handled in the clientConnected() slot where pending connections are connected to the readyRead() and disconnected() signals. The signals notify others that a new client has connected.
The readSocket() slot is called whenever data is ready to be read from a client socket. The slot reads individual lines from the socket, converts them from UTF-8, and emits the messageReceived() signal.
The clientDisconnected() slot is called whenever a client disconnects from the service. The slot emits a signal to notify others that a client has disconnected, and deletes the socket.
The sendMessage() slot is used to send a message to all connected clients. The message is converted into UTF-8 and appended with a newline before being sent to all clients.
When the chat server is stopped the service record is removed from the system SDP database, all connected client sockets are deleted, and the QRfcommServer instance is deleted.
The chat client is implemented by the ChatClient class. The ChatClient class is declared as:
The client creates a new QBluetoothSocket and connects to the remote service described by the remoteService parameter. Slots are connected to the sockets readyRead(), connected() and disconnected() signals.
On successful socket connection we emit a signal to notify others.
Similarly to the chat server, the readSocket() slot is called when data is available from the socket. Lines are read individually and converted from UTF-8. The messageReceived() signal is emitted.
The sendMessage() slot is used to send a message to the remote device. The message is converted to UTF-8 and a newline is appended.
To disconnect from the remote chat service, the QBluetoothSocket instance is deleted.
The main window of this example is the chat dialog, implemented in the Chat class. This class displays a chat session between a single ChatServer and zero or more ChatClients. The Chat class is declared as:
First we construct the user interface
We create an instance of the ChatServer and respond to its clientConnected(), clientDiconnected(), and messageReceived() signals.
In response to the clientConnected() and clientDisconnected() signals of the ChatServer, we display the typical 'X has joined chat.' and 'Y has left.' messages in the chat session.
Incoming messages from clients connected to the ChatServer are handled in the showMessage() slot. The message text tagged with the remote device name is displayed in the chat session.
In response to the connect button being clicked, the application starts service discovery and presents a list of discovered chat services on remote devices. A ChatClient for the service is selected by the user.
In reponse to the connected() signals from ChatClient, we display the a 'Joined chat with X.' message in the chat session.
Messages are sent to all remote devices via the ChatServer and ChatClient instances by emitting the sendMessage() signal.
We need to clean up ChatClient instances when the remote device forces a disconnect.
Files:
Qt5 alpha has been released. One of the features which I have been working on is a new syntax for signals and slot.This blog entry will present it.
Here is how you would connect a signal to a slot:
What really happens behind the scenes is that the SIGNAL
and SLOT
macros will convert their argument to a string. Then QObject::connect()
will compare those strings with the introspection data collected by the moc tool.
While working fine in general, we can identify some issues:
typedef
or namespacesIn the upcoming Qt5, an alternative syntax exist. The former syntax will still work. But you can now also use this new way of connecting your signals to your slots:
Which one is the more beautiful is a matter of taste. One can quickly get used to the new syntax.
So apart from the aesthetic point of view, let us go over some of the things that it brings us:
You will get a compiler error if you misspelled the signal or slot name, or if the arguments of your slot do not match those from the signal.
This might save you some time while you are doing some re-factoring and change the name or arguments of signals or slots.
An effort has been made, using static_assert to get nice compile errors if the arguments do not match or of you miss a Q_OBJECT
Not only you can now use typedef
or namespaces properly, but you can also connect signalsto slots that take arguments of different types if an implicit conversion is possible
In the following example, we connect a signal that has a QString
as a parameter to a slot that takes a QVariant
. It works because QVariant
has an implicit constructor that takes a QString
As you might have seen in the previous example, the slot was just declared as public
and not as slot
. Qt will indeed call directly the function pointer of the slot, andwill not need moc
introspection anymore. (It still needs it for the signal)
But what we can also do is connecting to any function or functor:
This can become very powerful when you associate that with boost or tr1::bind
.
Everything documented here works with the plain old C++98. But if you use compiler that supportsC++11, I really recommend you to use some of the language's new features.Lambda expressions are supportedby at least MSVC 2010, GCC 4.5, clang 3.1. For the last two, you need to pass -std=c++0x asa flag.
You can then write code like:
This allows you to write asynchronous code very easily.
Update: Also have a look what other C++11 features Qt5 offers.
It is time to try it out. Check out the alpha and start playing. Don't hesistate to report bugs.