tpsession initial import
[tpsession] / tpsession-0.1 / tpsession / tpsessionaccount.cpp
1 /*
2  * This file is part of TpSession
3  *
4  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
5  * Contact Kate Alhola  kate.alholanokia.com
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 #include "tpsessionaccount.h"
22 #include <TelepathyQt4/Message>
23
24 TpSessionAccount::TpSessionAccount(Tp::AccountManagerPtr am,const QString &objectPath):
25         mAcc(Tp::Account::create(am->dbusConnection(),am->busName(), objectPath))
26
27 {
28   connect(mAcc->becomeReady(),SIGNAL(finished(Tp::PendingOperation *)),SLOT(onReady(Tp::PendingOperation *)));
29   ready=false;
30   qDebug() << "TpSessionAccount::TpSessionAccount objectPath=" << objectPath;
31 };
32
33
34 void TpSessionAccount::onReady(Tp::PendingOperation *op)
35 {
36
37     acc = mAcc.data();
38     qDebug() << "TpSessionAccount::onReady cmName=" << acc->cmName() << "haveConnection=" <<
39         (acc->haveConnection()? ( acc->connection()->isReady() ? "Ready":"notReady"):"no");
40
41     if(acc->haveConnection()) {
42
43             connect(acc->connection()->becomeReady(Tp::Connection::FeatureRoster | Tp::Connection::FeatureSelfContact ),
44                 SIGNAL(finished(Tp::PendingOperation *)),
45                 SLOT(onContactsConnectionReady(Tp::PendingOperation *)));
46          if (acc->connection()->isReady() && acc->connection()->interfaces().contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_REQUESTS)) {
47             qDebug() << "TpSessionAccount::onReady: connecting to Connection.Interface.NewChannels";
48             connect(acc->connection()->requestsInterface(),
49                 SIGNAL(NewChannels(const Tp::ChannelDetailsList&)),
50                 SLOT(onNewChannels(const Tp::ChannelDetailsList&)));
51         }
52      }
53          else { // If there is no connection, we are ready now, else we are ready when contacts connection is ready
54             ready=true;
55             emit accountReady(this);
56         }
57      }
58
59 void TpSessionAccount::onContactsConnectionReady(Tp::PendingOperation *op)
60 {
61     if (op->isError()) {
62         qWarning() << "Connection cannot become ready" << acc->cmName();
63         return;
64     }
65
66     if (acc->connection()->interfaces().contains(TELEPATHY_INTERFACE_CONNECTION_INTERFACE_REQUESTS)) {
67             qDebug() << "TpSessionAccount::onContactsConectionReady: connecting to Connection.Interface.NewChannels";
68             connect(acc->connection()->requestsInterface(),
69                 SIGNAL(NewChannels(const Tp::ChannelDetailsList&)),
70                 SLOT(onNewChannels(const Tp::ChannelDetailsList&)));
71         } else qDebug() << "TpSessionAccount::onContactsConnectionReady: does NO have CONNECTION_INTERFACE_REQUESTS";
72     Tp::PendingReady *pr = qobject_cast<Tp::PendingReady *>(op);
73      contactsConn = Tp::ConnectionPtr(qobject_cast<Tp::Connection *>(pr->object()));
74 #if 0
75     connect(contactsConn->contactManager(),
76             SIGNAL(presencePublicationRequested(const Tp::Contacts &)),
77             SLOT(onPresencePublicationRequested(const Tp::Contacts &)));
78 #endif
79     qDebug() << "TpSessionAccount::onContactsConnectionReady "<< acc->cmName() ;
80     //    RosterItem *item;
81     bool exists;
82     myContacts=contactsConn->contactManager()->allKnownContacts();
83     foreach (const Tp::ContactPtr &contact, myContacts) {
84         qDebug() << "id=" <<contact->id() << " alias=" << contact->alias() << " presence=" << contact->presenceStatus()  ;
85         if(contact->id()==reqContact) {
86             addOutgoingChannel(contact);
87             reqContact="";
88         }
89     };
90     if(!reqContact.isEmpty() ) makeContactFromAddress(reqContact);
91     ready=true;
92     emit accountReady(this);
93 }
94
95 Tp::ContactPtr TpSessionAccount::getContactFromAddress(QString id)
96 {
97     Tp::ContactPtr p;
98     foreach (const Tp::ContactPtr &contact, myContacts) {
99     if(contact->id()==reqContact) return p=contact;
100     }
101     return p;
102 }
103
104 TpSessionChannel* TpSessionAccount::getChannelFromPeerAddress(QString id)
105 {
106   TpSessionChannel* p=NULL;
107     foreach (TpSessionChannel* channel, myChannels) {
108     if(channel->peerId()==id) return p=channel;
109     }
110     return p;
111 }
112
113 void TpSessionAccount::makeContactFromAddress(QString address)
114 {
115      reqContact=address;  // When we get retrieved signal, we check if it is this one
116      Tp::PendingContacts *pc=contactsConn->contactManager()->contactsForIdentifiers(QStringList(address));
117      connect(pc,SIGNAL(finished(Tp::PendingOperation *)),SLOT(onNewContactRetrieved(Tp::PendingOperation *)));
118 }
119
120 void TpSessionAccount::onNewContactRetrieved(Tp::PendingOperation *op)
121 {
122     Tp::PendingContacts *pcontacts = qobject_cast<Tp::PendingContacts *>(op);
123     QList<Tp::ContactPtr> contacts = pcontacts->contacts();
124     QString username = pcontacts->identifiers().first();
125     if (contacts.size() != 1 || !contacts.first()) {
126         qDebug() << "Unable to add contact " <<reqContact;
127         return;
128     }
129
130     Tp::ContactPtr contact = contacts.first();
131     qDebug() << "TpSessionAccount::onContactRetrieved" << reqContact;
132     if(!reqContact.isEmpty()) addOutgoingChannel(contacts.first());
133 }
134
135 void TpSessionAccount::sendMessageToAddress(QString address,QString message)
136 {
137     Tp::ContactPtr p;
138     TpSessionChannel* channel=getChannelFromPeerAddress(address);
139     if(channel)
140         channel->sendMessage(message); // We have already channel
141     else {
142         reqMessage=message;
143         p=getContactFromAddress(address); // Do we have contact ready ?
144         if(p.isNull())  // If not, create it
145             makeContactFromAddress(address); // Create and after created, send
146         else
147             addOutgoingChannel(p); // Create channel and when ready, send
148     };
149 }
150
151 void TpSessionAccount::addOutgoingChannel(const Tp::ContactPtr &contact)
152 {
153
154
155     qDebug() << "TpSessionAccount::addOutgoingChannel";
156
157      TpSessionChannel* newChannel=new TpSessionChannel(contact->manager()->connection(),contact);
158      connect(newChannel,SIGNAL(messageReceived(const Tp::ReceivedMessage &,TpSessionChannel *)),
159              SLOT(onMessageReceived(const Tp::ReceivedMessage &,TpSessionChannel *)));
160      connect(newChannel,SIGNAL(channelReady(TpSessionChannel *)),
161             SLOT(onOutgoingChannelReady(TpSessionChannel*)));
162      myChannels+=newChannel;
163
164 }
165
166 void TpSessionAccount::onOutgoingChannelReady(TpSessionChannel *ch)
167 {
168  qDebug() << "TpSessionAccoiunt::onOutgoingChannelReady";
169  emit channelReady(this);
170  if(!reqMessage.isEmpty()) ch->sendMessage(reqMessage);
171  reqMessage.clear();
172 }
173
174
175 void TpSessionAccount::onMessageSent(const Tp::Message &msg,Tp::MessageSendingFlags, const QString &flags)
176 {
177     qDebug() << "TpSessionAccount::onMessageSent";
178 };
179
180 void TpSessionAccount::onMessageReceived(const Tp::ReceivedMessage &msg,TpSessionChannel *ch)
181 {
182     qDebug() << "TpSessionAccount::onMessageReceived " << msg.text();
183     emit messageReceived(msg,this);
184 };
185
186 void TpSessionAccount::onNewChannels(const Tp::ChannelDetailsList &channels)
187 {
188
189     Tp::TextChannelPtr myIngoingTextChannel;
190     qDebug() << "TpSessionAccount::onNewChannels";
191     foreach (const Tp::ChannelDetails &details, channels) {
192         QString channelType = details.properties.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType")).toString();
193         bool requested = details.properties.value(QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".Requested")).toBool();
194         qDebug() << " channelType:" << channelType;
195         qDebug() << " requested  :" << requested;
196
197         if (channelType == TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT && !requested) {
198
199         myIngoingTextChannel = Tp::TextChannel::create(acc->connection(),details.channel.path(),details.properties);
200         qDebug() << "TpSessionAccount::onNewChannels path=" <<"path " << myIngoingTextChannel->objectPath();
201
202      TpSessionChannel* newChannel=new TpSessionChannel( myIngoingTextChannel);
203      connect(newChannel,SIGNAL(messageReceived(const Tp::ReceivedMessage &,TpSessionChannel *)),
204              SLOT(onMessageReceived(const Tp::ReceivedMessage &,TpSessionChannel *)));
205      myChannels+=newChannel;
206      }
207     }
208 }