Statistics
| Branch: | Tag: | Revision:

root / kadu-core / gui / windows / add-buddy-window.cpp @ fa3db8c8

History | View | Annotate | Download (16.8 kB)

1
/*
2
 * %kadu copyright begin%
3
 * Copyright 2011 Tomasz Rostanski (rozteck@interia.pl)
4
 * Copyright 2009, 2010, 2010, 2011 Piotr Galiszewski (piotr.galiszewski@kadu.im)
5
 * Copyright 2010 Wojciech Treter (juzefwt@gmail.com)
6
 * Copyright 2010, 2011 Piotr Dąbrowski (ultr@ultr.pl)
7
 * Copyright 2011 Sławomir Stępień (s.stepien@interia.pl)
8
 * Copyright 2009, 2010 Bartłomiej Zimoń (uzi18@o2.pl)
9
 * Copyright 2009, 2010, 2011 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com)
10
 * Copyright 2010, 2011 Bartosz Brachaczek (b.brachaczek@gmail.com)
11
 * %kadu copyright end%
12
 *
13
 * This program is free software; you can redistribute it and/or
14
 * modify it under the terms of the GNU General Public License as
15
 * published by the Free Software Foundation; either version 2 of
16
 * the License, or (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25
 */
26
27
#include <QtGui/QAction>
28
#include <QtGui/QCheckBox>
29
#include <QtGui/QComboBox>
30
#include <QtGui/QDialogButtonBox>
31
#include <QtGui/QFormLayout>
32
#include <QtGui/QLabel>
33
#include <QtGui/QLineEdit>
34
#include <QtGui/QPushButton>
35
#include <QtGui/QSortFilterProxyModel>
36
37
#include "accounts/account-manager.h"
38
#include "accounts/account.h"
39
#include "accounts/filter/protocol-filter.h"
40
#include "accounts/filter/writeable-contacts-list-filter.h"
41
#include "accounts/model/accounts-model.h"
42
#include "accounts/model/accounts-proxy-model.h"
43
#include "buddies/buddy-manager.h"
44
#include "buddies/buddy-preferred-manager.h"
45
#include "buddies/buddy.h"
46
#include "buddies/model/buddies-model.h"
47
#include "buddies/model/groups-model.h"
48
#include "contacts/contact-manager.h"
49
#include "contacts/contact.h"
50
#include "core/core.h"
51
#include "gui/widgets/accounts-combo-box.h"
52
#include "gui/widgets/groups-combo-box.h"
53
#include "gui/widgets/select-buddy-combo-box.h"
54
#include "icons/kadu-icon.h"
55
#include "identities/identity.h"
56
#include "misc/misc.h"
57
#include "model/roles.h"
58
#include "protocols/protocol-factory.h"
59
#include "protocols/protocol.h"
60
#include "protocols/roster.h"
61
#include "protocols/services/roster-service.h"
62
#include "talkable/filter/exclude-buddy-talkable-filter.h"
63
#include "protocols/services/subscription-service.h"
64
#include "url-handlers/url-handler-manager.h"
65
66
#include "add-buddy-window.h"
67
68
AddBuddyWindow::AddBuddyWindow(QWidget *parent, const Buddy &buddy, bool forceBuddyAccount) :
69
                QDialog(parent, Qt::Window), DesktopAwareObject(this), UserNameLabel(0), UserNameEdit(0),
70
                MobileAccountAction(0), EmailAccountAction(0), AccountCombo(0),
71
                GroupCombo(0), DisplayNameEdit(0), MergeBuddy(0), SelectBuddy(0), AskForAuthorization(0),
72
                AllowToSeeMeCheck(0), ErrorLabel(0), AddContactButton(0), MyBuddy(buddy),
73
                ForceBuddyAccount(forceBuddyAccount)
74
{
75
        setWindowRole("kadu-add-buddy");
76
        setWindowTitle(tr("Add buddy"));
77
        setAttribute(Qt::WA_DeleteOnClose);
78
79
        if (MyBuddy)
80
        {
81
                MyAccount = BuddyPreferredManager::instance()->preferredAccount(MyBuddy);
82
                if (!MyAccount)
83
                        MyBuddy = Buddy::null;
84
        }
85
86
        createGui();
87
        if (!MyBuddy)
88
                addFakeAccountsToComboBox();
89
}
90
91
AddBuddyWindow::~AddBuddyWindow()
92
{
93
        saveWindowGeometry(this, "General", "AddBuddyWindowGeometry");
94
}
95
96
void AddBuddyWindow::createGui()
97
{
98
        loadWindowGeometry(this, "General", "AddBuddyWindowGeometry", 0, 50, 425, 430);
99
100
        QVBoxLayout *mainLayout = new QVBoxLayout(this);
101
102
        QWidget *mainWidget = new QWidget(this);
103
        mainLayout->addWidget(mainWidget);
104
        mainLayout->addStretch(100);
105
106
        Layout = new QFormLayout(mainWidget);
107
108
        AccountCombo = new AccountsComboBox(MyBuddy.isNull(), ActionsProxyModel::NotVisibleWithOneRowSourceModel, this);
109
        AccountCombo->setIncludeIdInDisplay(true);
110
        AccountCombo->addFilter(new WriteableContactsListFilter(AccountCombo));
111
112
        if (MyBuddy)
113
        {
114
                AccountCombo->setCurrentAccount(MyAccount);
115
116
                ProtocolFilter *protocolFilter = new ProtocolFilter(AccountCombo);
117
                protocolFilter->setProtocolName(MyAccount.protocolName());
118
                AccountCombo->addFilter(protocolFilter);
119
        }
120
121
        if (MyBuddy && ForceBuddyAccount)
122
        {
123
                // NOTE: keep "%1 (%2)" consistent with AccountsModel::data() for DisplayRole, when IncludeIdInDisplay is true
124
                // TODO 0.10: remove such code duplication
125
                QString accountLabel = QString("<b>%1 (%2)</b>").arg(MyAccount.accountIdentity().name()).arg(MyAccount.id());
126
                Layout->addRow(tr("Account:"), new QLabel(accountLabel));
127
                AccountCombo->hide();
128
        }
129
        else
130
                Layout->addRow(tr("Account:"), AccountCombo);
131
132
        UserNameEdit = new QLineEdit(this);
133
        UserNameLabel = new QLabel(this);
134
135
        if (MyBuddy)
136
        {
137
                UserNameEdit->setText(MyBuddy.id(MyAccount));
138
                UserNameEdit->hide();
139
140
                Layout->addRow(UserNameLabel, new QLabel(QString("<b>%1</b>").arg(MyBuddy.id(MyAccount)), this));
141
        }
142
        else
143
                Layout->addRow(UserNameLabel, UserNameEdit);
144
145
        MergeBuddy = new QCheckBox(tr("Merge with existing buddy"), this);
146
        Layout->addRow(0, MergeBuddy);
147
148
        DisplayNameEdit = new QLineEdit(this);
149
        Layout->addRow(tr("Visible name:"), DisplayNameEdit);
150
151
        if (MyBuddy)
152
                DisplayNameEdit->setText(MyBuddy.display());
153
154
        connect(DisplayNameEdit, SIGNAL(textChanged(const QString &)), this, SLOT(setAddContactEnabled()));
155
156
        NonMergeWidgets.append(DisplayNameEdit);
157
158
        QLabel *hintLabel = new QLabel(tr("Enter a name for this buddy"));
159
        QFont hintLabelFont = hintLabel->font();
160
        hintLabelFont.setItalic(true);
161
        hintLabelFont.setPointSize(hintLabelFont.pointSize() - 2);
162
        hintLabel->setFont(hintLabelFont);
163
        Layout->addRow(0, hintLabel);
164
165
        NonMergeWidgets.append(hintLabel);
166
167
        GroupCombo = new GroupsComboBox(this);
168
        Layout->addRow(tr("Add in group:"), GroupCombo);
169
170
        NonMergeWidgets.append(GroupCombo);
171
172
        SelectBuddy = new SelectBuddyComboBox(this);
173
        SelectBuddy->addBeforeAction(new QAction(tr(" - Select buddy - "), SelectBuddy));
174
        SelectBuddy->setBaseModel(new BuddiesModel(SelectBuddy));
175
        SelectBuddy->setEnabled(false);
176
        SelectBuddy->setVisible(false);
177
        SelectBuddy->addFilter(new ExcludeBuddyTalkableFilter(Core::instance()->myself(), SelectBuddy));
178
        Layout->addRow(tr("Merge with:"), SelectBuddy);
179
180
        MergeWidgets.append(SelectBuddy);
181
182
        AskForAuthorization = new QCheckBox(tr("Ask contact for authorization"), this);
183
        Layout->addRow(0, AskForAuthorization);
184
185
        AllowToSeeMeCheck = new QCheckBox(tr("Allow buddy to see me when I'm available"), this);
186
        AllowToSeeMeCheck->setChecked(true);
187
        Layout->addRow(0, AllowToSeeMeCheck);
188
189
        NonMergeWidgets.append(AllowToSeeMeCheck);
190
191
        ErrorLabel = new QLabel(this);
192
        QFont labelFont = ErrorLabel->font();
193
        labelFont.setBold(true);
194
        ErrorLabel->setFont(labelFont);
195
        Layout->addRow(0, ErrorLabel);
196
197
        QDialogButtonBox *buttons = new QDialogButtonBox(mainWidget);
198
        mainLayout->addWidget(buttons);
199
200
        AddContactButton = new QPushButton(qApp->style()->standardIcon(QStyle::SP_DialogOkButton), tr("Add buddy"), this);
201
        AddContactButton->setDefault(true);
202
        connect(AddContactButton, SIGNAL(clicked(bool)), this, SLOT(accept()));
203
204
        QPushButton *cancel = new QPushButton(qApp->style()->standardIcon(QStyle::SP_DialogCancelButton), tr("Cancel"), this);
205
        connect(cancel, SIGNAL(clicked(bool)), this, SLOT(reject()));
206
207
        buttons->addButton(AddContactButton, QDialogButtonBox::AcceptRole);
208
        buttons->addButton(cancel, QDialogButtonBox::DestructiveRole);
209
210
        connect(UserNameEdit, SIGNAL(textChanged(const QString &)), this, SLOT(setAddContactEnabled()));
211
        connect(AccountCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(accountChanged()));
212
        connect(AccountCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateGui()));
213
        connect(AccountCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setAddContactEnabled()));
214
        connect(MergeBuddy, SIGNAL(toggled(bool)), this, SLOT(mergeToggled(bool)));
215
        connect(MergeBuddy, SIGNAL(toggled(bool)), this, SLOT(setAddContactEnabled()));
216
        connect(SelectBuddy, SIGNAL(currentIndexChanged(int)), this, SLOT(setAddContactEnabled()));
217
218
        mergeToggled(false);
219
220
        setAddContactEnabled();
221
        accountChanged();
222
        updateGui();
223
224
        setFixedHeight(height());
225
226
        if (MyBuddy)
227
                DisplayNameEdit->setFocus();
228
        else if (AccountCombo->currentAccount())
229
                UserNameEdit->setFocus();
230
        else
231
                AccountCombo->setFocus();
232
}
233
234
void AddBuddyWindow::addFakeAccountsToComboBox()
235
{
236
        MobileAccountAction = new QAction(KaduIcon("phone").icon(), tr("Mobile"), AccountCombo);
237
        AccountCombo->addAfterAction(MobileAccountAction);
238
239
        EmailAccountAction = new QAction(KaduIcon("mail-message-new").icon(), tr("E-mail"), AccountCombo);
240
        AccountCombo->addAfterAction(EmailAccountAction);
241
}
242
243
void AddBuddyWindow::displayErrorMessage(const QString &message)
244
{
245
        ErrorLabel->setText(message);
246
}
247
248
void AddBuddyWindow::setGroup(Group group)
249
{
250
        GroupCombo->setCurrentGroup(group);
251
}
252
253
bool AddBuddyWindow::isMobileAccount()
254
{
255
        return (MobileAccountAction && AccountCombo->currentAction() == MobileAccountAction);
256
}
257
258
bool AddBuddyWindow::isEmailAccount()
259
{
260
        return (EmailAccountAction && AccountCombo->currentAction() == EmailAccountAction);
261
}
262
263
void AddBuddyWindow::accountChanged()
264
{
265
        Account account = AccountCombo->currentAccount();
266
267
        if (LastSelectedAccount && LastSelectedAccount.protocolHandler())
268
        {
269
                disconnect(LastSelectedAccount.protocolHandler(), SIGNAL(connected(Account)), this, SLOT(setAddContactEnabled()));
270
                disconnect(LastSelectedAccount.protocolHandler(), SIGNAL(disconnected(Account)), this, SLOT(setAddContactEnabled()));
271
        }
272
273
        if (!account || !account.protocolHandler() || !account.protocolHandler()->subscriptionService())
274
        {
275
                AskForAuthorization->setEnabled(false);
276
                AskForAuthorization->setChecked(false);
277
        }
278
        else
279
        {
280
                connect(account.protocolHandler(), SIGNAL(connected(Account)), this, SLOT(setAddContactEnabled()));
281
                connect(account.protocolHandler(), SIGNAL(disconnected(Account)), this, SLOT(setAddContactEnabled()));
282
283
                AskForAuthorization->setEnabled(true);
284
                AskForAuthorization->setChecked(true);
285
        }
286
287
        LastSelectedAccount = account;
288
}
289
290
void AddBuddyWindow::updateAccountGui()
291
{
292
        if (UserNameLabel)
293
        {
294
                Account account = AccountCombo->currentAccount();
295
                if (account.isNull())
296
                        UserNameLabel->setText(tr("User ID:"));
297
                else
298
                        UserNameLabel->setText(account.protocolHandler()->protocolFactory()->idLabel());
299
        }
300
301
        MergeBuddy->setEnabled(true);
302
        AllowToSeeMeCheck->setEnabled(true);
303
}
304
305
void AddBuddyWindow::updateMobileGui()
306
{
307
        UserNameLabel->setText(tr("Mobile number:"));
308
        MergeBuddy->setChecked(false);
309
        MergeBuddy->setEnabled(false);
310
        AllowToSeeMeCheck->setEnabled(false);
311
}
312
313
void AddBuddyWindow::updateEmailGui()
314
{
315
        UserNameLabel->setText(tr("E-mail address:"));
316
        MergeBuddy->setChecked(false);
317
        MergeBuddy->setEnabled(false);
318
        AllowToSeeMeCheck->setEnabled(false);
319
}
320
321
void AddBuddyWindow::updateGui()
322
{
323
        if (isMobileAccount())
324
                updateMobileGui();
325
        else if (isEmailAccount())
326
                updateEmailGui();
327
        else
328
                updateAccountGui();
329
}
330
331
void AddBuddyWindow::validateData()
332
{
333
        AddContactButton->setEnabled(false);
334
335
        Account account = AccountCombo->currentAccount();
336
        if (account.isNull() || !account.protocolHandler() || !account.protocolHandler()->protocolFactory())
337
        {
338
                displayErrorMessage(tr("Account is not selected"));
339
                return;
340
        }
341
342
        if (account.protocolHandler()->rosterService() && !account.protocolHandler()->isConnected())
343
        {
344
                displayErrorMessage(tr("You must be connected to add contacts to this account"));
345
                return;
346
        }
347
348
        if (account.protocolHandler()->protocolFactory()->validateId(UserNameEdit->text()) != QValidator::Acceptable)
349
        {
350
                if (!UserNameEdit->text().isEmpty())
351
                        displayErrorMessage(tr("Entered user identification is invalid"));
352
                else
353
                        displayErrorMessage(tr("No user identification entered"));
354
                return;
355
        }
356
357
        Contact contact = ContactManager::instance()->byId(account, UserNameEdit->text(), ActionReturnNull);
358
        if (!contact.isAnonymous())
359
        {
360
                displayErrorMessage(tr("This contact is already available as <i>%1</i>").arg(contact.display(true)));
361
                return;
362
        }
363
364
        if (MergeBuddy->isChecked())
365
        {
366
                if (!SelectBuddy->currentTalkable().isValidBuddy())
367
                {
368
                        displayErrorMessage(tr("Select buddy to merge with"));
369
                        return;
370
                }
371
        }
372
        else
373
        {
374
                if (DisplayNameEdit->text().isEmpty())
375
                {
376
                        displayErrorMessage(tr("Enter visible name"));
377
                        return;
378
                }
379
                else
380
                {
381
                        Buddy existingBuddy = BuddyManager::instance()->byDisplay(DisplayNameEdit->text(), ActionReturnNull);
382
                        if (existingBuddy && existingBuddy != MyBuddy)
383
                        {
384
                                displayErrorMessage(tr("Visible name is already used for another buddy"));
385
                                return;
386
                        }
387
                }
388
        }
389
390
        AddContactButton->setEnabled(true);
391
        displayErrorMessage(QString());
392
}
393
394
void AddBuddyWindow::validateMobileData()
395
{
396
        Q_ASSERT(!MergeBuddy->isChecked());
397
398
        static QRegExp mobileRegularExpression("[0-9]{3,12}");
399
400
        if (!mobileRegularExpression.exactMatch(UserNameEdit->text()))
401
        {
402
                if (!UserNameEdit->text().isEmpty())
403
                        displayErrorMessage(tr("Entered mobile number is invalid"));
404
                else
405
                        displayErrorMessage(tr("No mobile number entered"));
406
                return;
407
        }
408
409
        if (DisplayNameEdit->text().isEmpty())
410
        {
411
                displayErrorMessage(tr("Enter visible name"));
412
                return;
413
        }
414
415
        AddContactButton->setEnabled(true);
416
        displayErrorMessage(QString());
417
}
418
419
void AddBuddyWindow::validateEmailData()
420
{
421
        Q_ASSERT(!MergeBuddy->isChecked());
422
423
        if (!UrlHandlerManager::instance()->mailRegExp().exactMatch(UserNameEdit->text()))
424
        {
425
                if (!UserNameEdit->text().isEmpty())
426
                        displayErrorMessage(tr("Entered e-mail is invalid"));
427
                else
428
                        displayErrorMessage(tr("No e-mail entered"));
429
                return;
430
        }
431
432
        if (DisplayNameEdit->text().isEmpty())
433
        {
434
                displayErrorMessage(tr("Enter visible name"));
435
                return;
436
        }
437
438
        AddContactButton->setEnabled(true);
439
        displayErrorMessage(QString());
440
}
441
442
void AddBuddyWindow::setAddContactEnabled()
443
{
444
        if (isMobileAccount())
445
                validateMobileData();
446
        else if (isEmailAccount())
447
                validateEmailData();
448
        else
449
                validateData();
450
}
451
452
void AddBuddyWindow::mergeToggled(bool toggled)
453
{
454
        setUpdatesEnabled(false);
455
456
        foreach (QWidget *widget, NonMergeWidgets)
457
        {
458
                widget->setVisible(!toggled);
459
                widget->setEnabled(!toggled);
460
461
                QWidget *label = Layout->labelForField(widget);
462
                if (label)
463
                        label->setVisible(!toggled);
464
        }
465
466
        foreach (QWidget *widget, MergeWidgets)
467
        {
468
                widget->setVisible(toggled);
469
                widget->setEnabled(toggled);
470
471
                QWidget *label = Layout->labelForField(widget);
472
                if (label)
473
                        label->setVisible(toggled);
474
        }
475
476
        if (toggled)
477
                AddContactButton->setText(tr("Merge with buddy"));
478
        else
479
                AddContactButton->setText(tr("Add buddy"));
480
481
        setUpdatesEnabled(true);
482
}
483
484
bool AddBuddyWindow::addContact()
485
{
486
        Account account = AccountCombo->currentAccount();
487
        if (account.isNull())
488
                return false;
489
490
        Buddy buddy;
491
492
        if (!MergeBuddy->isChecked())
493
        {
494
                if (MyBuddy.isNull())
495
                {
496
                        buddy = Buddy::create();
497
                        buddy.data()->setState(StorableObject::StateNew);
498
                }
499
                else
500
                        buddy = MyBuddy;
501
502
                BuddyManager::instance()->addItem(buddy);
503
504
                buddy.setAnonymous(false);
505
                buddy.setOfflineTo(!AllowToSeeMeCheck->isChecked());
506
507
                QString display = DisplayNameEdit->text().isEmpty() ? UserNameEdit->text() : DisplayNameEdit->text();
508
                buddy.setDisplay(display);
509
                buddy.addToGroup(GroupCombo->currentGroup());
510
        }
511
        else
512
        {
513
                buddy = SelectBuddy->currentTalkable().toBuddy();
514
                if (buddy.isNull())
515
                        return false;
516
        }
517
518
        Contact contact = ContactManager::instance()->byId(account, UserNameEdit->text(), ActionCreateAndAdd);
519
        contact.setOwnerBuddy(buddy);
520
521
        Roster::instance()->addContact(contact);
522
523
        if (!buddy.isOfflineTo())
524
                sendAuthorization(contact);
525
526
        if (AskForAuthorization->isChecked())
527
                askForAuthorization(contact);
528
529
        return true;
530
}
531
532
bool AddBuddyWindow::addMobile()
533
{
534
        Buddy buddy = Buddy::create();
535
        buddy.data()->setState(StorableObject::StateNew);
536
        buddy.setAnonymous(false);
537
        buddy.setMobile(UserNameEdit->text());
538
        buddy.setDisplay(DisplayNameEdit->text().isEmpty() ? UserNameEdit->text() : DisplayNameEdit->text());
539
        buddy.addToGroup(GroupCombo->currentGroup());
540
541
        BuddyManager::instance()->addItem(buddy);
542
543
        return true;
544
}
545
546
bool AddBuddyWindow::addEmail()
547
{
548
        Buddy buddy = Buddy::create();
549
        buddy.data()->setState(StorableObject::StateNew);
550
        buddy.setAnonymous(false);
551
        buddy.setEmail(UserNameEdit->text());
552
        buddy.setDisplay(DisplayNameEdit->text().isEmpty() ? UserNameEdit->text() : DisplayNameEdit->text());
553
        buddy.addToGroup(GroupCombo->currentGroup());
554
555
        BuddyManager::instance()->addItem(buddy);
556
557
        return true;
558
}
559
560
void AddBuddyWindow::accept()
561
{
562
        bool ok;
563
564
        if (isMobileAccount())
565
                ok = addMobile();
566
        else if (isEmailAccount())
567
                ok = addEmail();
568
        else
569
                ok = addContact();
570
571
        if (ok)
572
                QDialog::accept();
573
}
574
575
void AddBuddyWindow::askForAuthorization(const Contact &contact)
576
{
577
        Account account = AccountCombo->currentAccount();
578
579
        if (!account || !account.protocolHandler() || !account.protocolHandler()->subscriptionService())
580
                return;
581
582
        account.protocolHandler()->subscriptionService()->requestSubscription(contact);
583
}
584
585
void AddBuddyWindow::sendAuthorization(const Contact &contact)
586
{
587
        Account account = AccountCombo->currentAccount();
588
589
        if (!account || !account.protocolHandler() || !account.protocolHandler()->subscriptionService())
590
                return;
591
592
        account.protocolHandler()->subscriptionService()->resendSubscription(contact);
593
}