#include "tpsessionaccount.h"
#include <TelepathyQt4/Message>
+/**
+ * \class TpSessionAccount
+ * \headerfile <tpsessionaccount.h>
+ *
+ * TpSessionAccount class represents every account you have. As example account for “Ring” connection manager represents your cellular
+ * account and you may send and receive SMS with it. Gabble represents your GoogleTalk account if you have defined them.
+ * TpSessionAccounts are created by TpSession class,they are not intended to be created stand-alone
+
+ */
+/**
+ * \fn void TpSessionAccount::accountReady(TpSessionAccount *);
+ *
+ * Emitted when the account becomes ready
+ *
+ * \param TpSessionAccount pointer to account become ready
+ */
+/**
+ * \fn void TpSessionAccount::channelReady(TpSessionAccount *);
+ *
+ * Emitted when the account Manager becomes ready
+ *
+ * \param TpSession pointer to TpSession class
+ */
+/**
+ * \fn void TpSessionAccount::messageReceived(const Tp::ReceivedMessage &,TpSessionAccount *);
+ *
+ * Emitted when any of Account Managers recived message
+ *
+ * \param Tp::ReceivedMessage Message received
+ * \param TpSessionAccount pointer to account received message
+ */
+
+/**
+ * \fn void TpSessionAccount::newChannel(TpSessionAccount *,QString CjhannelType,QString peerId,const Tp::ChannelDetails &);
+ * \param TpSession pointer to TpSession class
+ * \param ChannelType type of Channel, TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT for text channel, TELEPATHY_INTERFACE_CHANNEL_TYPE_STREAMED_MEDIA for steram media, as exmple for incoming call
+ * \param peedId PeerId, as example caller telephone number
+ * \param channeDetails needed if you would like to create a channel. For text chanels TpSession creates channel automatically. For calls, Maemo Call UI handles callcreation
+ */
+
+/**
+ * Construct a new TpSessionAccount object. This constructor is called by TpSession class when new account is created or fetched from account manager. It is not inended to be used stand alone
+ *
+ * \param am Telepathy-Qt4 account manager for this account
+ * \param objectPath Dbus object path tonew account
+ */
TpSessionAccount::TpSessionAccount(Tp::AccountManagerPtr am,const QString &objectPath):
mAcc(Tp::Account::create(am->dbusConnection(),am->busName(), objectPath))
{
connect(mAcc->becomeReady(),SIGNAL(finished(Tp::PendingOperation *)),SLOT(onReady(Tp::PendingOperation *)));
ready=false;
- qDebug() << "TpSessionAccount::TpSessionAccount objectPath=" << objectPath;
+ // qDebug() << "TpSessionAccount::TpSessionAccount objectPath=" << objectPath;
};
void TpSessionAccount::onReady(Tp::PendingOperation *op)
{
-
+ Q_UNUSED(op);
acc = mAcc.data();
- qDebug() << "TpSessionAccount::onReady cmName=" << acc->cmName() << "haveConnection=" <<
- (acc->haveConnection()? ( acc->connection()->isReady() ? "Ready":"notReady"):"no");
+ // qDebug() << "TpSessionAccount::onReady cmName=" << acc->cmName() << "haveConnection=" <<
+ // (acc->haveConnection()? ( acc->connection()->isReady() ? "Ready":"notReady"):"no");
if(acc->haveConnection()) {
SIGNAL(finished(Tp::PendingOperation *)),
SLOT(onContactsConnectionReady(Tp::PendingOperation *)));
if (acc->connection()->isReady() && acc->connection()->interfaces().contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_REQUESTS)) {
- qDebug() << "TpSessionAccount::onReady: connecting to Connection.Interface.NewChannels";
+ // qDebug() << "TpSessionAccount::onReady: connecting to Connection.Interface.NewChannels";
connect(acc->connection()->requestsInterface(),
SIGNAL(NewChannels(const Tp::ChannelDetailsList&)),
SLOT(onNewChannels(const Tp::ChannelDetailsList&)));
}
if (acc->connection()->interfaces().contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_REQUESTS)) {
- qDebug() << "TpSessionAccount::onContactsConectionReady: connecting to Connection.Interface.NewChannels";
+ // // qDebug() << "TpSessionAccount::onContactsConectionReady: connecting to Connection.Interface.NewChannels";
connect(acc->connection()->requestsInterface(),
SIGNAL(NewChannels(const Tp::ChannelDetailsList&)),
SLOT(onNewChannels(const Tp::ChannelDetailsList&)));
SIGNAL(presencePublicationRequested(const Tp::Contacts &)),
SLOT(onPresencePublicationRequested(const Tp::Contacts &)));
#endif
- qDebug() << "TpSessionAccount::onContactsConnectionReady "<< acc->cmName() ;
+ // qDebug() << "TpSessionAccount::onContactsConnectionReady "<< acc->cmName() ;
// RosterItem *item;
- bool exists;
myContacts=contactsConn->contactManager()->allKnownContacts();
foreach (const Tp::ContactPtr &contact, myContacts) {
- qDebug() << "id=" <<contact->id() << " alias=" << contact->alias() << " presence=" << contact->presenceStatus() ;
+ // qDebug() << "id=" <<contact->id() << " alias=" << contact->alias() << " presence=" << contact->presenceStatus() ;
if(contact->id()==reqContact) {
addOutgoingChannel(contact);
reqContact="";
emit accountReady(this);
}
+
+/**
+ * Fetch Tp::ContactPtr for contact with given address. Contact is searched among contacts returned by contact manager for ths account.
+ * All connecions managers does not return contacts, as example Ring telephony contact manager does not. Gabble for Googletalk or Spirit for Skype does
+ * return contacts-
+ *
+ * \param id Contact address/id, as example email address, telephone number etc. Only exact matches
+ * \return TpContactPtr, if nontact is not returned TpContactPtr.isNull() is true
+ */
+
Tp::ContactPtr TpSessionAccount::getContactFromAddress(QString id)
{
+ Q_UNUSED(id);
Tp::ContactPtr p;
foreach (const Tp::ContactPtr &contact, myContacts) {
- if(contact->id()==reqContact) return p=contact;
+ if(contact->id()==id) return p=contact;
}
return p;
}
+/**
+ * Fetch TpSessionChannel for with given address. Contact is searched among active channels for this account.
+ *
+ *
+ * \param id Contact address/id, as example email address, telephone number etc. Only exact matches
+ * \return Pointer to TpSessionChannel or NULL if nit found
+ */
TpSessionChannel* TpSessionAccount::getChannelFromPeerAddress(QString id)
{
TpSessionChannel* p=NULL;
foreach (TpSessionChannel* channel, myChannels) {
- if(channel->peerId()==id) return p=channel;
+ if(channel->peerId()==id) p=channel;
}
return p;
}
+/**
+ * Creates new contact with given address. This function is Acynchronous, it sends request to contact manager for contact creation,
+ *
+ * \param address Contact address/id, as example email address, telephone number etc.
+ * \return true in success
+ *
+ * \return emits contactRetrieved(Tp:.contactPtr,bool success,bool requested)
+*/
-void TpSessionAccount::makeContactFromAddress(QString address)
+bool TpSessionAccount::makeContactFromAddress(QString address)
{
+ if(!contactsConn) return false; // No contacts connection, return fail
reqContact=address; // When we get retrieved signal, we check if it is this one
Tp::PendingContacts *pc=contactsConn->contactManager()->contactsForIdentifiers(QStringList(address));
connect(pc,SIGNAL(finished(Tp::PendingOperation *)),SLOT(onNewContactRetrieved(Tp::PendingOperation *)));
+ return true;
}
void TpSessionAccount::onNewContactRetrieved(Tp::PendingOperation *op)
{
+ Tp::ContactPtr contact;
Tp::PendingContacts *pcontacts = qobject_cast<Tp::PendingContacts *>(op);
QList<Tp::ContactPtr> contacts = pcontacts->contacts();
QString username = pcontacts->identifiers().first();
if (contacts.size() != 1 || !contacts.first()) {
qDebug() << "Unable to add contact " <<reqContact;
+ emit contactRetrieved(contact,false,false);
+ if(!reqMessage.isEmpty()) { // If there is requesting messsage, can't queue if contact failed
+ emit messageQueued(this,false);
+ reqMessage.clear();
+ };
+
return;
}
- Tp::ContactPtr contact = contacts.first();
- qDebug() << "TpSessionAccount::onContactRetrieved" << reqContact;
- if(!reqContact.isEmpty()) addOutgoingChannel(contacts.first());
+ contact = contacts.first();
+ // qDebug() << "TpSessionAccount::onContactRetrieved" << reqContact;
+ if(!reqContact.isEmpty()) {
+ addOutgoingChannel(contacts.first());
+ emit contactRetrieved(contact,true,true);
+ }
+ else
+ emit contactRetrieved(contact,true,false);
}
+/**
+ * Send message to given address. This function is compled Acynchronous function that may produce multiple state transitions beforecomletion.
+ * If there is already existing TpSessionChannel for this contact, it simply queues message for sending and no forther transitions are needed
+ * If there are no hannel, it first check is there contact for this address, if is, it requests new channel to be created for ths channel and message
+ * is left waiting untill channel is created. If there is no contact, it sends request fr contact creation and when contact is created state machine
+ * proceeds to channel creation.
+ *
+ * MessageSent() signal is emitted when completed
+ *
+ * \param address Contact address/id, as example email address, telephone number etc.
+ * \param message Message string
+ */
void TpSessionAccount::sendMessageToAddress(QString address,QString message)
{
Tp::ContactPtr p;
TpSessionChannel* channel=getChannelFromPeerAddress(address);
- if(channel)
+ if(channel) {
+ if(TpSession::tpsDebug()) qDebug() << "TpSessionAccount::sendMessageToAddress peer:" << channel->peerId() << "queuing:" << message;
channel->sendMessage(message); // We have already channel
+ emit messageQueued(this,true);
+ }
else {
reqMessage=message;
p=getContactFromAddress(address); // Do we have contact ready ?
{
- qDebug() << "TpSessionAccount::addOutgoingChannel";
+ if(TpSession::tpsDebug()) qDebug() << "TpSessionAccount::addOutgoingChannel";
TpSessionChannel* newChannel=new TpSessionChannel(contact->manager()->connection(),contact);
connect(newChannel,SIGNAL(messageReceived(const Tp::ReceivedMessage &,TpSessionChannel *)),
SLOT(onMessageReceived(const Tp::ReceivedMessage &,TpSessionChannel *)));
+ connect(newChannel,SIGNAL(messageSent(const Tp::Message &,Tp::MessageSendingFlags, const QString &,TpSessionChannel *)),
+ SLOT(onMessageSent(const Tp::Message &,Tp::MessageSendingFlags, const QString &,TpSessionChannel *)));
connect(newChannel,SIGNAL(channelReady(TpSessionChannel *)),
SLOT(onOutgoingChannelReady(TpSessionChannel*)));
+ connect(newChannel,SIGNAL(channelDestroyed(TpSessionChannel *)),
+ SLOT(onChannelDestroyed(TpSessionChannel*)));
myChannels+=newChannel;
}
void TpSessionAccount::onOutgoingChannelReady(TpSessionChannel *ch)
{
- qDebug() << "TpSessionAccoiunt::onOutgoingChannelReady";
+ if(TpSession::tpsDebug()) qDebug() << "TpSessionAccount::onOutgoingChannelReady";
emit channelReady(this);
- if(!reqMessage.isEmpty()) ch->sendMessage(reqMessage);
+ if(!reqMessage.isEmpty()) {
+ if(TpSession::tpsDebug()) qDebug() << "TpSessionAccount::onOutgoingChannelReady peer:" << ch->peerId() << "queuing:" << reqMessage;
+ ch->sendMessage(reqMessage);
+ emit messageQueued(this,true);
+ };
reqMessage.clear();
}
-void TpSessionAccount::onMessageSent(const Tp::Message &msg,Tp::MessageSendingFlags, const QString &flags)
+void TpSessionAccount::onMessageSent(const Tp::Message &msg,Tp::MessageSendingFlags, const QString &flags,TpSessionChannel *ch)
{
- qDebug() << "TpSessionAccount::onMessageSent";
+ Q_UNUSED(flags);
+ if(TpSession::tpsDebug()) qDebug() << "TpSessionAccount::onMessageSent peer:" << ch->peerId() <<"txt:" << msg.text();
+ emit messageSent(msg,this);
};
void TpSessionAccount::onMessageReceived(const Tp::ReceivedMessage &msg,TpSessionChannel *ch)
{
- qDebug() << "TpSessionAccount::onMessageReceived " << msg.text();
- emit messageReceived(msg,this);
+ Q_UNUSED(ch);
+ // qDebug() << "TpSessionAccount::onMessageReceived " << msg.text();
+ emit messageReceived(msg,this);
};
void TpSessionAccount::onNewChannels(const Tp::ChannelDetailsList &channels)
{
Tp::TextChannelPtr myIngoingTextChannel;
- qDebug() << "TpSessionAccount::onNewChannels";
+ // qDebug() << "TpSessionAccount::onNewChannels";
foreach (const Tp::ChannelDetails &details, channels) {
QString channelType = details.properties.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType")).toString();
+ QString targetId = details.properties.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetID")).toString();
bool requested = details.properties.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".Requested")).toBool();
- qDebug() << " channelType:" << channelType;
- qDebug() << " requested :" << requested;
+ // qDebug() << " channelType:" << channelType <<" requested :" << requested << " targetId" << targetId;
+ emit newChannel(this,channelType,targetId,details);
if (channelType == TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT && !requested) {
- myIngoingTextChannel = Tp::TextChannel::create(acc->connection(),details.channel.path(),details.properties);
- qDebug() << "TpSessionAccount::onNewChannels path=" <<"path " << myIngoingTextChannel->objectPath();
+ myIngoingTextChannel = Tp::TextChannel::create(acc->connection(),details.channel.path(),details.properties);
+ // qDebug() << "TpSessionAccount::onNewChannels path=" <<"path " << myIngoingTextChannel->objectPath();
- TpSessionChannel* newChannel=new TpSessionChannel( myIngoingTextChannel);
- connect(newChannel,SIGNAL(messageReceived(const Tp::ReceivedMessage &,TpSessionChannel *)),
+ TpSessionChannel* newChannel=new TpSessionChannel( myIngoingTextChannel);
+ connect(newChannel,SIGNAL(messageReceived(const Tp::ReceivedMessage &,TpSessionChannel *)),
SLOT(onMessageReceived(const Tp::ReceivedMessage &,TpSessionChannel *)));
- myChannels+=newChannel;
- }
+ connect(newChannel,SIGNAL(messageSent(const Tp::Message &,Tp::MessageSendingFlags, const QString &,TpSessionChannel *)),
+ SLOT(onMessageSent(const Tp::Message &,Tp::MessageSendingFlags, const QString &,TpSessionChannel *)));
+ connect(newChannel,SIGNAL(channelDestroyed(TpSessionChannel *)),
+ SLOT(onChannelDestroyed(TpSessionChannel*)));
+ myChannels+=newChannel;
+ }
+ if (channelType == TELEPATHY_INTERFACE_CHANNEL_TYPE_STREAMED_MEDIA && !requested) {
+ // qDebug() << "Incoming call" ;
+ }
}
}
+
+void TpSessionAccount::onChannelDestroyed(TpSessionChannel *ch)
+{
+ if(TpSession::tpsDebug()) qDebug() << "TpSessionAccount::onMessageSent peer:" << ch->peerId();
+ myChannels.remove(ch);
+};