Development/Tutorials/Decibel/Handling TextChannels: Difference between revisions
Grundleborg (talk | contribs) (add the source code from SVN) |
Grundleborg (talk | contribs) (add sub-subheadings) |
||
Line 51: | Line 51: | ||
Now that we have defined our <tt>Decibel::ChannelHandler</tt> subclass, we need to implement its methods. | Now that we have defined our <tt>Decibel::ChannelHandler</tt> subclass, we need to implement its methods. | ||
====Constructor==== | |||
<code cppqt> | <code cppqt> | ||
MyTextChannelHandler::MyTextChannelHandler(QObject * parent) : | MyTextChannelHandler::MyTextChannelHandler(QObject * parent) : | ||
Line 60: | Line 61: | ||
The constructor is very simple. We just pass the <tt>parent</tt> object on to the parent class and initialise our member variables to <tt>0</tt>. | The constructor is very simple. We just pass the <tt>parent</tt> object on to the parent class and initialise our member variables to <tt>0</tt>. | ||
====Destructor==== | |||
<code cppqt> | <code cppqt> | ||
MyTextChannelHandler::~MyTextChannelHandler() | MyTextChannelHandler::~MyTextChannelHandler() | ||
Line 66: | Line 68: | ||
The destructor is even simpler. We don't need to do anything in it because Qt will handle the deletion of child objects automatically. | The destructor is even simpler. We don't need to do anything in it because Qt will handle the deletion of child objects automatically. | ||
====handleChannel()==== | |||
<code cppqt> | <code cppqt> | ||
bool MyTextChannelHandler::handleChannel(QtTapioca::Connection * connection, | bool MyTextChannelHandler::handleChannel(QtTapioca::Connection * connection, | ||
Line 93: | Line 96: | ||
</code> | </code> | ||
====onCloseChannel()==== | |||
<code cppqt> | <code cppqt> | ||
void MyTextChannelHandler::onCloseChannel() | void MyTextChannelHandler::onCloseChannel() | ||
Line 101: | Line 105: | ||
</code> | </code> | ||
====onMessageReceived()==== | |||
<code cppqt> | <code cppqt> | ||
void MyTextChannelHandler::onMessageReceived() | void MyTextChannelHandler::onMessageReceived() |
Revision as of 05:27, 12 March 2008
Tutorial Series | Decibel Tutorial |
Previous | C++, Qt, KDE4 development environment |
What's Next | |
Further Reading | CMake |
Abstract
This tutorial will walk you through the process of creating a simple application that uses Decibel's TextChannels to communicate via arbitrary instant messaging networks using telepathy. From the result of this tutorial, only a few more lines of code are needed to produce a functioning text based instant messaging client.
This tutorial is based on the simpleclient demo included with Decibel. An explanation of using the simpleclient demo can be found here.
In this tutorial, we only pick out the important parts of the source code to discuss. The complete working source code for this example can be found here in KDE's SVN Repository.
ChannelHandler class
The first class we will need to create is an implementation of the Decibel::ChannelHandler interface.
The Class Definition
Here is the class definition for our implementation of the Decibel::ChannelHandler interface. It is explained below.
class MyTextChannelHandler : public Decibel::ChannelHandler
{
Q_OBJECT
public:
explicit MyTextChannelHandler(QObject * parent = 0);
~MyTextChannelHandler();
bool handleChannel(QtTapioca::Connection *, QtTapioca::Channel *, const bool);
public slots:
void onMessageReceived();
void onCloseChannel();
private:
QtTapioca::Connection * m_connection;
QtTapioca::TextChannel * m_channel;
};
We must inherit from Decibel::ChannelHandler which is the interface definition for handling incoming Channels. We reimplement the constructor, Destructor and the handleChannel() method as well as adding two slots of our own. We also create the member variables m_connecion and m_channel which will hold the QtTapioca::Connection and QtTapioca::Channel objects that are received by the handleChannel method.
The Class Implementation
Now that we have defined our Decibel::ChannelHandler subclass, we need to implement its methods.
Constructor
MyTextChannelHandler::MyTextChannelHandler(QObject * parent) :
ChannelHandler(parent),
m_connection(0),
m_channel(0)
{ }
The constructor is very simple. We just pass the parent object on to the parent class and initialise our member variables to 0.
Destructor
MyTextChannelHandler::~MyTextChannelHandler()
{ }
The destructor is even simpler. We don't need to do anything in it because Qt will handle the deletion of child objects automatically.
handleChannel()
bool MyTextChannelHandler::handleChannel(QtTapioca::Connection * connection,
QtTapioca::Channel * channel,
const bool)
{
Q_ASSERT(connection != 0);
Q_ASSERT(channel != 0);
if (m_connection != 0) { return false; }
m_channel = dynamic_cast<QtTapioca::TextChannel*>(channel);
if (m_channel == 0)
{
return false;
}
m_connection = connection;
connect(m_channel, SIGNAL(messageReceived(const QtTapioca::TextChannel *, const QtTapioca::TextChannel::Message &)),
this, SLOT(onMessageReceived()));
connect(m_channel, SIGNAL(closed()), this, SLOT(onCloseChannel()));
onMessageReceived();
return true;
}
onCloseChannel()
void MyTextChannelHandler::onCloseChannel()
{
m_connection = 0;
m_channel = 0;
}
onMessageReceived()
void MyTextChannelHandler::onMessageReceived()
{
QList<QtTapioca::TextChannel::Message> message_list = m_channel->pendingMessages();
for (QList<QtTapioca::TextChannel::Message>::const_iterator
message = message_list.constBegin();
message != message_list.constEnd(); ++message)
{
if (message->type() == QtTapioca::TextChannel::Message::Normal &&
message->contents() == QString("ping?"))
{ m_channel->sendMessage(QString("pong!")); }
m_channel->acknowledge(*message);
}
}
The main.cpp file
TODO
The .component File
TODO
The .service File
TODO
CMakeLists.txt
SET(QT_DONT_USE_QTGUI "YES")
INCLUDE(${QT_USE_FILE})
SET(SERVICE_FILE "org.kde.SimpleClient.service")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_BINARY_DIR}/src/client
${CMAKE_SOURCE_DIR}/src/client
${QT_QTCORE_INCLUDE_DIR}
${TELEPATHY_QT_INCLUDE_DIR}
${TAPIOCA_QT_INCLUDE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/${SERVICE_FILE}.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${SERVICE_FILE}"
)
- ######### simpleclient demo #########
SET(simpleclient_SRCS
simpleclient.cpp
mytextchannelhandler.cpp
)
SET(simpleclient_MOC_HDRS
mytextchannelhandler.h
)
QT4_WRAP_CPP(simpleclient_MOC_SRCS ${simpleclient_MOC_HDRS})
ADD_EXECUTABLE(decibel_simpleclient_demo ${simpleclient_SRCS}
${simpleclient_MOC_SRCS}
)
TARGET_LINK_LIBRARIES(decibel_simpleclient_demo
${QT_LIBRARIES}
${TAPIOCA_QT_LIBRARIES}
decibel
)
INSTALL(TARGETS decibel_simpleclient_demo DESTINATION ${DEMO_INSTALL_DIR})
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SERVICE_FILE}
DESTINATION ${DBUS_SERVICES_INSTALL_DIR}
)
INSTALL(FILES org.kde.SimpleClient.TextChannel.component
DESTINATION ${COMPONENT_SEARCH_DIR}
)
Running our Application
TODO