File indexing completed on 2023-12-03 05:01:48

0001 /*
0002     Class that auto configures link-local xmpp account
0003     Copyright (C) 2011  Martin Klapetek <martin.klapetek@gmail.com>
0004     Copyright (C) 2012  Daniele E. Domenichelli <daniele.domenichelli@gmail.com>
0005 
0006     This library is free software; you can redistribute it and/or
0007     modify it under the terms of the GNU Lesser General Public
0008     License as published by the Free Software Foundation; either
0009     version 2.1 of the License, or (at your option) any later version.
0010 
0011     This library is distributed in the hope that it will be useful,
0012     but WITHOUT ANY WARRANTY; without even the implied warranty of
0013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014     Lesser General Public License for more details.
0015 
0016     You should have received a copy of the GNU Lesser General Public
0017     License along with this library; if not, write to the Free Software
0018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0019 */
0020 
0021 
0022 #include "salut-enabler.h"
0023 
0024 #include <TelepathyQt/ConnectionManager>
0025 #include <TelepathyQt/ProfileManager>
0026 #include <TelepathyQt/AccountManager>
0027 #include <TelepathyQt/PendingOperation>
0028 #include <TelepathyQt/PendingReady>
0029 #include <TelepathyQt/PendingAccount>
0030 
0031 #include <KDebug>
0032 #include <KUser>
0033 #include <KLocalizedString>
0034 
0035 #include <QtGui/QFrame>
0036 #include <KTp/global-presence.h>
0037 
0038 #include "salut-details-dialog.h"
0039 #include "salut-message-widget.h"
0040 
0041 #define TP_PROP_ACCOUNT_ENABLED (QLatin1String("org.freedesktop.Telepathy.Account.Enabled"))
0042 #define TP_PROP_ACCOUNT_SERVICE (QLatin1String("org.freedesktop.Telepathy.Account.Service"))
0043 
0044 const QLatin1String salutConnManager("salut");
0045 const QLatin1String localXmppProtocol("local-xmpp");
0046 const QLatin1String firstNamePar("first-name");
0047 const QLatin1String lastNamePar("last-name");
0048 const QLatin1String nickNamePar("nickname");
0049 
0050 class SalutEnabler::Private
0051 {
0052 public:
0053     Private(SalutEnabler* parent)
0054         : q(parent),
0055           detailsDialog(0),
0056           messageWidget(0)
0057     {
0058     }
0059 
0060     SalutEnabler *q;
0061 
0062     Tp::ConnectionManagerPtr connectionManager;
0063     Tp::ProfileManagerPtr profileManager;
0064     Tp::AccountManagerPtr accountManager;
0065     Tp::ProfilePtr profile;
0066     QVariantMap values;
0067     SalutDetailsDialog *detailsDialog;
0068     SalutMessageWidget *messageWidget;
0069     QWeakPointer<QFrame> salutMessageFrame;
0070     QString displayName;
0071     KTp::GlobalPresence *globalPresence;
0072 };
0073 
0074 SalutEnabler::SalutEnabler(const Tp::AccountManagerPtr accountManager, QObject *parent)
0075     : QObject(parent),
0076       d(new Private(this))
0077 {
0078     d->accountManager = accountManager;
0079 
0080     d->globalPresence = new KTp::GlobalPresence(this);
0081     d->globalPresence->setAccountManager(accountManager);
0082 
0083     d->connectionManager = Tp::ConnectionManager::create(salutConnManager);
0084     connect(d->connectionManager->becomeReady(),
0085             SIGNAL(finished(Tp::PendingOperation*)),
0086             SLOT(onConnectionManagerReady(Tp::PendingOperation*)));
0087 }
0088 
0089 SalutEnabler::~SalutEnabler()
0090 {
0091     delete d;
0092 }
0093 
0094 void SalutEnabler::onConnectionManagerReady(Tp::PendingOperation* op)
0095 {
0096     if (op->isError()) {
0097         kWarning() << "Creating ConnectionManager failed:" << op->errorName() << op->errorMessage();
0098     }
0099 
0100     if (!d->connectionManager->isValid()) {
0101         kWarning() << "Invalid ConnectionManager";
0102     }
0103 
0104     d->profileManager = Tp::ProfileManager::create(QDBusConnection::sessionBus());
0105 
0106     // FIXME: Until all distros ship correct profile files, we should fake them
0107     connect(d->profileManager->becomeReady(Tp::Features() << Tp::ProfileManager::FeatureFakeProfiles),
0108             SIGNAL(finished(Tp::PendingOperation*)),
0109             SLOT(onProfileManagerReady(Tp::PendingOperation*)));
0110 }
0111 
0112 void SalutEnabler::onProfileManagerReady(Tp::PendingOperation* op)
0113 {
0114     if (op->isError()) {
0115         kWarning() << "Creating ProfileManager failed:" << op->errorName() << op->errorMessage();
0116     }
0117 
0118     // Get the protocol's parameters and values.
0119     Tp::ProtocolInfo protocolInfo = d->connectionManager->protocol(localXmppProtocol);
0120     Tp::ProtocolParameterList parameters = protocolInfo.parameters();
0121 
0122     d->profile = d->profileManager->profilesForCM(salutConnManager).first();
0123 
0124     Q_ASSERT(!d->profile.isNull());
0125     Q_ASSERT(d->profile->isValid());
0126     Q_ASSERT(d->profile->protocolName() == localXmppProtocol);
0127     if (d->profile.isNull() || !d->profile->isValid() || d->profile->protocolName() != localXmppProtocol) {
0128         kWarning() << "Something went wrong with telepathy salut";
0129     }
0130 
0131     KUser user = KUser();
0132     QString name = user.property(KUser::FullName).toString();
0133     QString nick = user.loginName();
0134     int lastSpacePosition = name.lastIndexOf(QLatin1Char(' '));
0135     QString lastname = name.mid(lastSpacePosition + 1);
0136     QString firstName = name.left(lastSpacePosition);
0137 
0138     d->values.insert(firstNamePar, firstName);
0139     d->values.insert(lastNamePar, lastname);
0140     d->values.insert(nickNamePar, nick);
0141 
0142     Q_EMIT userInfoReady();
0143 }
0144 
0145 QFrame* SalutEnabler::frameWidget(QWidget* parent)
0146 {
0147     if (d->salutMessageFrame.isNull()) {
0148         d->salutMessageFrame = new QFrame(parent);
0149     }
0150     d->salutMessageFrame.data()->setMinimumWidth(parent->width());
0151     d->salutMessageFrame.data()->setFrameShape(QFrame::StyledPanel);
0152 
0153     d->messageWidget = new SalutMessageWidget(d->salutMessageFrame.data());
0154     d->messageWidget->setParams(d->values[firstNamePar].toString(),
0155                                 d->values[lastNamePar].toString(),
0156                                 d->values[nickNamePar].toString());
0157     d->messageWidget->hide();
0158 
0159     QPropertyAnimation *animation = new QPropertyAnimation(d->salutMessageFrame.data(), "minimumHeight", d->messageWidget);
0160     animation->setDuration(150);
0161     animation->setStartValue(0);
0162     animation->setEndValue(d->messageWidget->sizeHint().height());
0163     animation->start();
0164 
0165     connect(animation, SIGNAL(finished()),
0166             d->messageWidget, SLOT(animatedShow()));
0167 
0168     connect(d->messageWidget, SIGNAL(timeout()),
0169             this, SLOT(onUserAccepted()));
0170 
0171     connect(d->messageWidget, SIGNAL(configPressed()),
0172             this, SLOT(onUserWantingChanges()));
0173 
0174     connect(d->messageWidget, SIGNAL(cancelPressed()),
0175             this, SLOT(onUserCancelled()));
0176 
0177     return d->salutMessageFrame.data();
0178 }
0179 
0180 void SalutEnabler::onUserAccepted()
0181 {
0182     // FIXME: In some next version of tp-qt4 there should be a convenience class for this
0183     // https://bugs.freedesktop.org/show_bug.cgi?id=33153
0184     QVariantMap properties;
0185 
0186     if (d->accountManager->supportedAccountProperties().contains(TP_PROP_ACCOUNT_SERVICE)) {
0187         properties.insert(TP_PROP_ACCOUNT_SERVICE, d->profile->serviceName());
0188     }
0189     if (d->accountManager->supportedAccountProperties().contains(TP_PROP_ACCOUNT_ENABLED)) {
0190         properties.insert(TP_PROP_ACCOUNT_ENABLED, true);
0191     }
0192 
0193     if (d->displayName.isEmpty())
0194     {
0195         QString lastname = d->values[lastNamePar].toString();
0196         QString firstname = d->values[firstNamePar].toString();
0197         QString nickname = d->values[nickNamePar].toString();
0198 
0199         if (!firstname.isEmpty()) {
0200             d->displayName = firstname;
0201         }
0202 
0203         if (!lastname.isEmpty()) {
0204             if (!d->displayName.isEmpty()) {
0205                 d->displayName.append(QString::fromLatin1(" %1").arg(lastname));
0206             } else {
0207                 d->displayName = lastname;
0208             }
0209         }
0210 
0211         if (!nickname.isEmpty()) {
0212             if (!d->displayName.isEmpty()) {
0213                 d->displayName.append(QString::fromLatin1(" (%1)").arg(nickname));
0214             } else {
0215                 d->displayName = nickname;
0216             }
0217         }
0218         if (d->displayName.isEmpty()) {
0219             //FIXME: let the user know that he reached a very strange situation
0220             kWarning() << "All fields are empty";
0221         }
0222     }
0223 
0224     Tp::PendingAccount *pa = d->accountManager->createAccount(d->profile->cmName(),
0225                                                               d->profile->protocolName(),
0226                                                               d->displayName,
0227                                                               d->values,
0228                                                               properties);
0229 
0230     connect(pa,
0231             SIGNAL(finished(Tp::PendingOperation*)),
0232             SLOT(onAccountCreated(Tp::PendingOperation*)));
0233 }
0234 
0235 void SalutEnabler::onAccountCreated(Tp::PendingOperation* op)
0236 {
0237     kDebug() << "Account created";
0238     if (op->isError()) {
0239         kWarning() << "Creating Account failed:" << op->errorName() << op->errorMessage();
0240     }
0241 
0242     if (op->isError()) {
0243         Q_EMIT feedbackMessage(i18n("Failed to create account"),
0244                                i18n("Possibly not all required fields are valid"),
0245                                KMessageWidget::Error);
0246         kWarning() << "Adding Account failed:" << op->errorName() << op->errorMessage();
0247         return;
0248     }
0249 
0250     // Get the PendingAccount.
0251     Tp::PendingAccount *pendingAccount = qobject_cast<Tp::PendingAccount*>(op);
0252     if (!pendingAccount) {
0253                 Q_EMIT feedbackMessage(i18n("Something went wrong with Telepathy"),
0254                                        QString(),
0255                                        KMessageWidget::Error);
0256         kWarning() << "Method called with wrong type.";
0257         return;
0258     }
0259 
0260     pendingAccount->account()->setRequestedPresence(d->globalPresence->requestedPresence());
0261     pendingAccount->account()->setServiceName(d->profile->serviceName());
0262 
0263     d->salutMessageFrame.data()->deleteLater();;
0264 
0265     Q_EMIT done();
0266 }
0267 
0268 void SalutEnabler::onUserWantingChanges()
0269 {
0270     d->detailsDialog = new SalutDetailsDialog(d->profileManager, d->connectionManager, 0);
0271 
0272     connect(d->detailsDialog, SIGNAL(dialogAccepted(QString,QVariantMap)),
0273             this, SLOT(onDialogAccepted(QString,QVariantMap)));
0274 
0275     connect(d->detailsDialog, SIGNAL(rejected()),
0276             this, SLOT(onUserCancelled()));
0277 
0278     connect(d->detailsDialog, SIGNAL(feedbackMessage(QString,QString,KMessageWidget::MessageType)),
0279             this, SIGNAL(feedbackMessage(QString,QString,KMessageWidget::MessageType)));
0280 
0281     d->detailsDialog->exec();
0282 }
0283 
0284 void SalutEnabler::onDialogAccepted(const QString &displayName, const QVariantMap &values)
0285 {
0286     kDebug() << values;
0287     d->displayName = displayName;
0288     d->values.insert(firstNamePar, values[firstNamePar].toString());
0289     d->values.insert(lastNamePar, values[lastNamePar].toString());
0290     d->values.insert(nickNamePar, values[nickNamePar].toString());
0291     onUserAccepted();
0292 }
0293 
0294 void SalutEnabler::onUserCancelled()
0295 {
0296     d->messageWidget->animatedHide();
0297 
0298     QPropertyAnimation *animation = new QPropertyAnimation(d->salutMessageFrame.data(), "maximumHeight", d->messageWidget);
0299     animation->setDuration(150);
0300     animation->setStartValue(d->messageWidget->sizeHint().height());
0301     animation->setEndValue(0);
0302 
0303     QTimer::singleShot(300, animation, SLOT(start()));
0304 
0305     connect(animation, SIGNAL(finished()),
0306             d->salutMessageFrame.data(), SLOT(deleteLater()));
0307 
0308     connect(animation, SIGNAL(finished()),
0309             this, SIGNAL(cancelled()));
0310 }