File indexing completed on 2023-11-26 08:16:46

0001 /*
0002  * Add contact dialog
0003  *
0004  * Copyright (C) 2011 David Edmundson <kde@davidedmundson.co.uk>
0005  * Copyright (C) 2012 George Kiagiadakis <kiagiadakis.george@gmail.com>
0006  *
0007  * This library is free software; you can redistribute it and/or
0008  * modify it under the terms of the GNU Lesser General Public
0009  * License as published by the Free Software Foundation; either
0010  * version 2.1 of the License, or (at your option) any later version.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Lesser General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Lesser General Public
0018  * License along with this library; if not, write to the Free Software
0019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
0020  */
0021 
0022 #include "add-contact-dialog.h"
0023 #include "ui_add-contact-dialog.h"
0024 #include "debug.h"
0025 
0026 #include <KTp/types.h>
0027 
0028 #include <QObject>
0029 #include <QCloseEvent>
0030 #include <QDialogButtonBox>
0031 
0032 #include <KMessageBox>
0033 #include <KLocalizedString>
0034 
0035 #include <TelepathyQt/AccountManager>
0036 #include <TelepathyQt/Account>
0037 #include <TelepathyQt/Connection>
0038 #include <TelepathyQt/ContactManager>
0039 #include <TelepathyQt/PendingContacts>
0040 #include <TelepathyQt/Filter>
0041 #include <TelepathyQt/AccountSet>
0042 #include <TelepathyQt/PendingReady>
0043 
0044 namespace KTp {
0045 
0046 class KTPCOMMONINTERNALS_NO_EXPORT SubscribableAccountFilter : public Tp::AccountFilter
0047 {
0048 public:
0049     SubscribableAccountFilter() : Tp::AccountFilter()
0050     {
0051     }
0052 
0053     bool isValid() const override
0054     {
0055         //return whether the filter is valid which is always true as this filter is hardcoded
0056         return true;
0057     }
0058 
0059     bool matches(const Tp::AccountPtr &account) const override
0060     {
0061         //if there's no connection we can't add contacts as we have no contactmanager
0062         if (! account->connection()) {
0063             return false;
0064         }
0065 
0066         //only show items which can add a contact (i.e hide accounts like IRC which are online but there's no point listing)
0067         if (! account->connection()->contactManager()->canRequestPresenceSubscription()){
0068             return false;
0069         }
0070         return true;
0071     }
0072 };
0073 
0074 
0075 struct KTPCOMMONINTERNALS_NO_EXPORT AddContactDialog::Private
0076 {
0077     Private() :
0078         ui(new Ui::AddContactDialog),
0079         acceptInProgress(false)
0080     {}
0081 
0082     Ui::AddContactDialog *ui;
0083     bool acceptInProgress;
0084     QDialogButtonBox *buttonBox;
0085 };
0086 
0087 AddContactDialog::AddContactDialog(const Tp::AccountManagerPtr &accountManager, QWidget *parent) :
0088     QDialog(parent),
0089     d(new Private)
0090 {
0091     setWindowTitle(i18n("Add new contact"));
0092     setWindowIcon(QIcon::fromTheme(QLatin1String("list-add-user")));
0093 
0094     QWidget *widget = new QWidget(this);
0095     d->ui->setupUi(widget);
0096 
0097     d->buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
0098     connect(d->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
0099     connect(d->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
0100 
0101 
0102     QVBoxLayout *mainLayout = new QVBoxLayout(this);
0103     mainLayout->addWidget(widget);
0104     mainLayout->addWidget(d->buttonBox);
0105 
0106     setLayout(mainLayout);
0107 
0108     Tp::AccountFilterPtr filter = Tp::AccountFilterPtr(new KTp::SubscribableAccountFilter());
0109     Tp::AccountSetPtr accountSet = accountManager->filterAccounts(filter);
0110 
0111     d->ui->accountCombo->setAccountSet(accountSet);
0112     updateSubscriptionMessageVisibility();
0113 
0114     connect(d->ui->accountCombo, SIGNAL(currentIndexChanged(int)), SLOT(updateSubscriptionMessageVisibility()));
0115 
0116     //bodge.
0117     //Wtih KPeople support we don't enable FeatureRoster
0118     //We need FeatureRoster in order to determine canRequestPresenceSubscription();
0119     //so we upgrade any accounts here
0120 
0121     //See https://bugs.kde.org/show_bug.cgi?id=324698
0122     Q_FOREACH(const Tp::AccountPtr &account, accountManager->allAccounts()) {
0123         if (account->connection()) {
0124             Tp::PendingOperation *op = account->connection()->becomeReady(Tp::Connection::FeatureRoster);
0125             op->setProperty("account", QVariant::fromValue<Tp::AccountPtr>(account));
0126             connect(op, SIGNAL(finished(Tp::PendingOperation*)), SLOT(_k_onAccountUpgraded(Tp::PendingOperation*)));
0127         }
0128     }
0129     //end bodge
0130 
0131     d->ui->screenNameLineEdit->setFocus();
0132 }
0133 
0134 AddContactDialog::~AddContactDialog()
0135 {
0136     delete d->ui;
0137     delete d;
0138 }
0139 
0140 //bodge
0141 void AddContactDialog::_k_onAccountUpgraded(Tp::PendingOperation* op)
0142 {
0143     const Tp::AccountPtr &account = op->property("account").value<Tp::AccountPtr>();
0144     //pretend the account changed.
0145     //emit that the account properties have changed to invalidate the filter
0146     QMetaObject::invokeMethod(account.data(), "propertyChanged", Q_ARG(QString, QString()));
0147 }
0148 //end bodge
0149 
0150 void AddContactDialog::accept()
0151 {
0152     Tp::AccountPtr account = d->ui->accountCombo->currentAccount();
0153 
0154     if (account.isNull()) {
0155         KMessageBox::sorry(this, i18n("No account selected."));
0156     } else if (account->connection().isNull()) {
0157         KMessageBox::sorry(this, i18n("The requested account has been disconnected "
0158                                       "and so the contact could not be added."));
0159     } else if (d->ui->screenNameLineEdit->text().isEmpty()) {
0160         KMessageBox::sorry(this, i18n("You did not specify the name of the contact to add."));
0161     } else {
0162         QStringList identifiers = QStringList() << d->ui->screenNameLineEdit->text();
0163         qCDebug(KTP_WIDGETS) << "Requesting contacts for identifiers:" << identifiers;
0164 
0165         Tp::PendingContacts *pendingContacts = account->connection()->contactManager()->contactsForIdentifiers(identifiers);
0166         connect(pendingContacts, SIGNAL(finished(Tp::PendingOperation*)),
0167                 this, SLOT(_k_onContactsForIdentifiersFinished(Tp::PendingOperation*)));
0168 
0169         setInProgress(true);
0170     }
0171 }
0172 
0173 void AddContactDialog::closeEvent(QCloseEvent *e)
0174 {
0175     // ignore close event if we are in the middle of an operation
0176     if (!d->acceptInProgress) {
0177         QDialog::closeEvent(e);
0178     }
0179 }
0180 
0181 void AddContactDialog::_k_onContactsForIdentifiersFinished(Tp::PendingOperation *op)
0182 {
0183     if (op->isError()) {
0184         qWarning() << "Failed to retrieve a contact for the given identifier"
0185                    << op->errorName() << op->errorMessage();
0186         KMessageBox::sorry(this, i18n("Failed to create new contact."));
0187         setInProgress(false);
0188     } else {
0189         qCDebug(KTP_WIDGETS) << "Requesting presence subscription";
0190 
0191         Tp::PendingContacts *pc = qobject_cast<Tp::PendingContacts*>(op);
0192         connect(pc->manager()->requestPresenceSubscription(pc->contacts(), d->ui->messageLineEdit->text()),
0193                 SIGNAL(finished(Tp::PendingOperation*)),
0194                 SLOT(_k_onRequestPresenceSubscriptionFinished(Tp::PendingOperation*)));
0195     }
0196 }
0197 
0198 void AddContactDialog::_k_onRequestPresenceSubscriptionFinished(Tp::PendingOperation *op)
0199 {
0200     if (op->isError()) {
0201         qWarning() << "Failed to request presence subscription"
0202                    << op->errorName() << op->errorMessage();
0203         KMessageBox::sorry(this, i18n("Failed to request presence subscription "
0204                                       "from the requested contact."));
0205         setInProgress(false);
0206     } else {
0207         QDialog::accept();
0208     }
0209 }
0210 
0211 void AddContactDialog::updateSubscriptionMessageVisibility()
0212 {
0213     Tp::AccountPtr account = d->ui->accountCombo->currentAccount();
0214     if (account && account->connection()->contactManager()->subscriptionRequestHasMessage()) {
0215         d->ui->messageLineEdit->show();
0216         d->ui->messageLineLabel->show();
0217     } else {
0218         d->ui->messageLineEdit->hide();
0219         d->ui->messageLineLabel->hide();
0220     }
0221 }
0222 
0223 void AddContactDialog::setInProgress(bool inProgress)
0224 {
0225     d->acceptInProgress = inProgress;
0226     layout()->parentWidget()->setEnabled(!inProgress);
0227     d->buttonBox->setEnabled(!inProgress);
0228 }
0229 
0230 } //namespace KTp