1 /*
2 * Add contact dialog
3 *
4 * Copyright (C) 2011 David Edmundson <kde@davidedmundson.co.uk>
5 * Copyright (C) 2012 George Kiagiadakis <kiagiadakis.george@gmail.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
22 #include "add-contact-dialog.h"
23 #include "ui_add-contact-dialog.h"
24 #include "debug.h"
25
26 #include <KTp/types.h>
27
28 #include <QObject>
29 #include <QCloseEvent>
30 #include <QDialogButtonBox>
31
32 #include <KMessageBox>
33 #include <KLocalizedString>
34
35 #include <TelepathyQt/AccountManager>
36 #include <TelepathyQt/Account>
37 #include <TelepathyQt/Connection>
38 #include <TelepathyQt/ContactManager>
39 #include <TelepathyQt/PendingContacts>
40 #include <TelepathyQt/Filter>
41 #include <TelepathyQt/AccountSet>
42 #include <TelepathyQt/PendingReady>
43
44 namespace KTp {
45
46 class KTPCOMMONINTERNALS_NO_EXPORT SubscribableAccountFilter : public Tp::AccountFilter
47 {
48 public:
SubscribableAccountFilter()49 SubscribableAccountFilter() : Tp::AccountFilter()
50 {
51 }
52
isValid() const53 bool isValid() const override
54 {
55 //return whether the filter is valid which is always true as this filter is hardcoded
56 return true;
57 }
58
matches(const Tp::AccountPtr & account) const59 bool matches(const Tp::AccountPtr &account) const override
60 {
61 //if there's no connection we can't add contacts as we have no contactmanager
62 if (! account->connection()) {
63 return false;
64 }
65
66 //only show items which can add a contact (i.e hide accounts like IRC which are online but there's no point listing)
67 if (! account->connection()->contactManager()->canRequestPresenceSubscription()){
68 return false;
69 }
70 return true;
71 }
72 };
73
74
75 struct KTPCOMMONINTERNALS_NO_EXPORT AddContactDialog::Private
76 {
PrivateKTp::AddContactDialog::Private77 Private() :
78 ui(new Ui::AddContactDialog),
79 acceptInProgress(false)
80 {}
81
82 Ui::AddContactDialog *ui;
83 bool acceptInProgress;
84 QDialogButtonBox *buttonBox;
85 };
86
AddContactDialog(const Tp::AccountManagerPtr & accountManager,QWidget * parent)87 AddContactDialog::AddContactDialog(const Tp::AccountManagerPtr &accountManager, QWidget *parent) :
88 QDialog(parent),
89 d(new Private)
90 {
91 setWindowTitle(i18n("Add new contact"));
92 setWindowIcon(QIcon::fromTheme(QLatin1String("list-add-user")));
93
94 QWidget *widget = new QWidget(this);
95 d->ui->setupUi(widget);
96
97 d->buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
98 connect(d->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
99 connect(d->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
100
101
102 QVBoxLayout *mainLayout = new QVBoxLayout(this);
103 mainLayout->addWidget(widget);
104 mainLayout->addWidget(d->buttonBox);
105
106 setLayout(mainLayout);
107
108 Tp::AccountFilterPtr filter = Tp::AccountFilterPtr(new KTp::SubscribableAccountFilter());
109 Tp::AccountSetPtr accountSet = accountManager->filterAccounts(filter);
110
111 d->ui->accountCombo->setAccountSet(accountSet);
112 updateSubscriptionMessageVisibility();
113
114 connect(d->ui->accountCombo, SIGNAL(currentIndexChanged(int)), SLOT(updateSubscriptionMessageVisibility()));
115
116 //bodge.
117 //Wtih KPeople support we don't enable FeatureRoster
118 //We need FeatureRoster in order to determine canRequestPresenceSubscription();
119 //so we upgrade any accounts here
120
121 //See https://bugs.kde.org/show_bug.cgi?id=324698
122 Q_FOREACH(const Tp::AccountPtr &account, accountManager->allAccounts()) {
123 if (account->connection()) {
124 Tp::PendingOperation *op = account->connection()->becomeReady(Tp::Connection::FeatureRoster);
125 op->setProperty("account", QVariant::fromValue<Tp::AccountPtr>(account));
126 connect(op, SIGNAL(finished(Tp::PendingOperation*)), SLOT(_k_onAccountUpgraded(Tp::PendingOperation*)));
127 }
128 }
129 //end bodge
130
131 d->ui->screenNameLineEdit->setFocus();
132 }
133
~AddContactDialog()134 AddContactDialog::~AddContactDialog()
135 {
136 delete d->ui;
137 delete d;
138 }
139
140 //bodge
_k_onAccountUpgraded(Tp::PendingOperation * op)141 void AddContactDialog::_k_onAccountUpgraded(Tp::PendingOperation* op)
142 {
143 const Tp::AccountPtr &account = op->property("account").value<Tp::AccountPtr>();
144 //pretend the account changed.
145 //emit that the account properties have changed to invalidate the filter
146 QMetaObject::invokeMethod(account.data(), "propertyChanged", Q_ARG(QString, QString()));
147 }
148 //end bodge
149
accept()150 void AddContactDialog::accept()
151 {
152 Tp::AccountPtr account = d->ui->accountCombo->currentAccount();
153
154 if (account.isNull()) {
155 KMessageBox::sorry(this, i18n("No account selected."));
156 } else if (account->connection().isNull()) {
157 KMessageBox::sorry(this, i18n("The requested account has been disconnected "
158 "and so the contact could not be added."));
159 } else if (d->ui->screenNameLineEdit->text().isEmpty()) {
160 KMessageBox::sorry(this, i18n("You did not specify the name of the contact to add."));
161 } else {
162 QStringList identifiers = QStringList() << d->ui->screenNameLineEdit->text();
163 qCDebug(KTP_WIDGETS) << "Requesting contacts for identifiers:" << identifiers;
164
165 Tp::PendingContacts *pendingContacts = account->connection()->contactManager()->contactsForIdentifiers(identifiers);
166 connect(pendingContacts, SIGNAL(finished(Tp::PendingOperation*)),
167 this, SLOT(_k_onContactsForIdentifiersFinished(Tp::PendingOperation*)));
168
169 setInProgress(true);
170 }
171 }
172
closeEvent(QCloseEvent * e)173 void AddContactDialog::closeEvent(QCloseEvent *e)
174 {
175 // ignore close event if we are in the middle of an operation
176 if (!d->acceptInProgress) {
177 QDialog::closeEvent(e);
178 }
179 }
180
_k_onContactsForIdentifiersFinished(Tp::PendingOperation * op)181 void AddContactDialog::_k_onContactsForIdentifiersFinished(Tp::PendingOperation *op)
182 {
183 if (op->isError()) {
184 qWarning() << "Failed to retrieve a contact for the given identifier"
185 << op->errorName() << op->errorMessage();
186 KMessageBox::sorry(this, i18n("Failed to create new contact."));
187 setInProgress(false);
188 } else {
189 qCDebug(KTP_WIDGETS) << "Requesting presence subscription";
190
191 Tp::PendingContacts *pc = qobject_cast<Tp::PendingContacts*>(op);
192 connect(pc->manager()->requestPresenceSubscription(pc->contacts(), d->ui->messageLineEdit->text()),
193 SIGNAL(finished(Tp::PendingOperation*)),
194 SLOT(_k_onRequestPresenceSubscriptionFinished(Tp::PendingOperation*)));
195 }
196 }
197
_k_onRequestPresenceSubscriptionFinished(Tp::PendingOperation * op)198 void AddContactDialog::_k_onRequestPresenceSubscriptionFinished(Tp::PendingOperation *op)
199 {
200 if (op->isError()) {
201 qWarning() << "Failed to request presence subscription"
202 << op->errorName() << op->errorMessage();
203 KMessageBox::sorry(this, i18n("Failed to request presence subscription "
204 "from the requested contact."));
205 setInProgress(false);
206 } else {
207 QDialog::accept();
208 }
209 }
210
updateSubscriptionMessageVisibility()211 void AddContactDialog::updateSubscriptionMessageVisibility()
212 {
213 Tp::AccountPtr account = d->ui->accountCombo->currentAccount();
214 if (account && account->connection()->contactManager()->subscriptionRequestHasMessage()) {
215 d->ui->messageLineEdit->show();
216 d->ui->messageLineLabel->show();
217 } else {
218 d->ui->messageLineEdit->hide();
219 d->ui->messageLineLabel->hide();
220 }
221 }
222
setInProgress(bool inProgress)223 void AddContactDialog::setInProgress(bool inProgress)
224 {
225 d->acceptInProgress = inProgress;
226 layout()->parentWidget()->setEnabled(!inProgress);
227 d->buttonBox->setEnabled(!inProgress);
228 }
229
230 } //namespace KTp
231