Fixes: NB#290445 - China variant:Settings option goes missing in configured Gmail...
[accounts-sso:libaccounts-ui.git] / lib / AccountsUI / account-settings-page.cpp
1 /*
2  * This file is part of accounts-ui
3  *
4  * Copyright (C) 2009-2010 Nokia Corporation.
5  *
6  * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * version 2.1 as published by the Free Software Foundation.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * 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
20  * 02110-1301 USA
21  */
22
23 //project
24 #include "account-settings-page-priv.h"
25 #include "provider-plugin-process.h"
26 #include "service-settings-widget.h"
27 #include "credentialdialog.h"
28 #include "service-model.h"
29 #include "sort-service-model.h"
30 #include "avatar-selector.h"
31
32 //Accounts
33 #include <Accounts/Account>
34 #include <Accounts/Provider>
35
36 //Telepathy
37 #include <TelepathyQt4/PendingReady>
38 #include <TelepathyQt4/Types>
39 #include <TelepathyQt4/AccountSet>
40 #include <TelepathyQt4/Contact>
41 #include <TelepathyQt4/PendingContactInfo>
42 #include <TelepathyQt4/PendingContacts>
43 #include <TelepathyQt4/PendingHandles>
44 #include <TelepathyQt4/PendingVariant>
45 #include <TelepathyQt4/ConnectionLowlevel>
46 #include <TelepathyQt4/AvatarSpec>
47 #include <TelepathyQt4/Debug>
48 #include <TelepathyQt4/Constants>
49
50 //Meegotouch
51 #include <MLayout>
52 #include <MMessageBox>
53 #include <MAction>
54 #include <MButton>
55 #include <MImageWidget>
56 #include <MSeparator>
57 #include <MLocale>
58 #include <MPannableViewport>
59 #include <MPositionIndicator>
60 #include <MBasicListItem>
61 #include <MImageWidget>
62
63 #include "basic-header-widget.h"
64 #include "avatar-selector.h"
65
66 //Qt
67 #include <QDebug>
68 #include <QBuffer>
69
70 #include <sysinfo.h>
71
72 #define INFO_BANNER_TIMEOUT 3000
73
74 using namespace AccountsUI;
75
76 AvatarListItem::AvatarListItem(QGraphicsWidget *parent)
77         : MBasicListItem(MBasicListItem::IconWithTitle, parent)
78 {
79     setStyleName("CommonLargePanel");
80     setObjectName("wgServiceSettingsWidgetListItem");
81
82     horizontalLayout = new MLayout(this);
83
84     horizontalLayout->setContentsMargins(7, 0, 0, 0);
85     MLinearLayoutPolicy *horizontalLayoutPolicy
86             = new MLinearLayoutPolicy(horizontalLayout, Qt::Horizontal);
87     horizontalLayoutPolicy->setSpacing(0);
88
89     MLayout *titleSubtitleLayout = new MLayout(horizontalLayout);
90     titleSubtitleLayout->setContentsMargins(0, 0, 0, 0);
91     MLinearLayoutPolicy *titleSubtitleLayoutPolicy = new MLinearLayoutPolicy(titleSubtitleLayout, Qt::Vertical);
92     titleSubtitleLayoutPolicy->setSpacing(0);
93
94     titleLabelWidget()->setStyleName("CommonTitleInverted");
95     titleSubtitleLayoutPolicy->addItem(titleLabelWidget(), Qt::AlignLeft | Qt::AlignTop);
96
97     avatarImage = new MImageWidget();
98     avatarImage->setStyleName("CommonMainIcon");
99     horizontalLayoutPolicy->addItem(avatarImage, Qt::AlignLeft);
100     horizontalLayoutPolicy->addItem(titleSubtitleLayout, Qt::AlignLeft | Qt::AlignCenter);
101
102     MImageWidget *image = imageWidget();
103     image->setImage("icon-m-common-drilldown-arrow-inverse");
104     image->setStyleName("CommonDrillDownIcon");
105     image->setObjectName("wgServiceSettingsWidgetDrillDownIcon");
106     image->setVisible(true);
107     horizontalLayoutPolicy->addItem(image, Qt::AlignCenter);
108 }
109
110 AvatarListItem::~AvatarListItem()
111 {}
112
113 QGraphicsLayout *AvatarListItem::createLayout()
114 {
115     return horizontalLayout;
116 }
117
118 void AvatarListItem::setImage(const QImage &image)
119 {
120     avatarImage->setImage(image);
121 }
122
123 void AvatarListItem::setImage(const QString &id)
124 {
125     avatarImage->setImage(id);
126 }
127
128 AccountSettingsPagePrivate::AccountSettingsPagePrivate(
129     AbstractAccountSetupContext *context):
130     context(context),
131     account(0),
132     enableButton(0),
133     syncHandler(0),
134     changePasswordDialogStarted(false),
135     panel(0),
136     layout(0),
137     panelPolicy(0),
138     saving(false),
139     preferredWidth(avatar_width_medium),
140     preferredHeight(avatar_height_medium)
141 {
142     account = context->account();
143     serviceList = account->services();
144     abstractContexts.append(context);
145     panel = new MWidgetController();
146     syncHandler = new AccountSyncHandler(this);
147     connect(syncHandler, SIGNAL(syncStateChanged(const SyncState&)),
148             this, SLOT(onSyncStateChanged(const SyncState&)));
149 }
150
151 bool AccountSettingsPagePrivate::hasSingleService() const
152 {
153     return serviceList.count() <= 1;
154 }
155
156 void AccountSettingsPagePrivate::saveSettings()
157 {
158     Q_Q(AccountSettingsPage);
159
160     if (saving) return;
161     saving = true;
162
163     q->setProgressIndicatorVisible(true);
164     qDebug() << Q_FUNC_INFO;
165     if (enableButton) {
166         bool state = enableButton->isChecked();
167         if (serviceList.count() == 1) {
168             account->selectService(serviceList.at(0));
169             if (account->enabled() != state)
170                 account->setEnabled(state);
171         } else if (serviceList.count() > 1) {
172             foreach (AbstractServiceSetupContext *serviceContext, contexts) {
173                 const Accounts::Service *service = serviceContext->service();
174                 QMap<QString, bool>::iterator i =
175                         serviceStatusMap.find(service->name());
176                 if (i == serviceStatusMap.end())
177                     continue;
178                 account->selectService(service);
179                 if (account->enabled() != i.value())
180                         serviceContext->enable(i.value());
181                 serviceStatusMap.remove(i.key());
182             }
183         }
184
185         context->account()->selectService(NULL);
186         if (account->enabled() != state)
187             account->setEnabled(state);
188     }
189     if (accountPtr) {
190         if (accountPtr->isOnline()) {
191             Tp::Avatar newAvatar;
192             newAvatar.avatarData = avatarImageData;
193             newAvatar.MIMEType = avatarImageType;
194             connect((Tp::Account *)accountPtr.data(), SIGNAL(avatarChanged (const Tp::Avatar &)),
195                     this, SLOT(onAvatarChange(const Tp::Avatar &)));
196             op = accountPtr->setAvatar(newAvatar);
197             connect(op, SIGNAL(finished(Tp::PendingOperation *)), this, SLOT(finishedCalled(Tp::PendingOperation *)));
198         } else
199             qDebug() << "Account Not Online";
200     }
201
202     //we should call only validate. Storing will be handled
203     //in onSyncStateChangted func.
204     syncHandler->validate(abstractContexts);
205 }
206
207 void AccountSettingsPagePrivate::finishedCalled(Tp::PendingOperation *op)
208 {
209     qDebug() << Q_FUNC_INFO;
210     if (op->isError())
211         qDebug() << op->errorMessage();
212 }
213
214 void AccountSettingsPagePrivate::onSyncStateChanged(const SyncState &state)
215 {
216     qDebug() << Q_FUNC_INFO;
217
218     Q_Q(AccountSettingsPage);
219     switch (state) {
220         case NotValidated:
221             qDebug() << Q_FUNC_INFO << "NotValidated";
222             q->setProgressIndicatorVisible(false);
223             //Saving the settings on back button press
224             saving = false;
225             break;
226         case Validated:
227             qDebug() << Q_FUNC_INFO << "Validated";
228             syncHandler->store(abstractContexts);
229             break;
230         case NotStored:
231             qDebug() << Q_FUNC_INFO << "NotStored";
232             connect(context->account(), SIGNAL(synced()),
233                     ProviderPluginProcess::instance(), SLOT(quit()));
234             context->account()->sync();
235             break;
236         case Stored:
237             qDebug() << Q_FUNC_INFO << "Stored";
238             connect(context->account(), SIGNAL(synced()),
239                     ProviderPluginProcess::instance(), SLOT(quit()));
240             context->account()->sync();
241             break;
242         default:
243             return;
244     }
245 }
246
247 void AccountSettingsPagePrivate::openChangePasswordDialog()
248 {
249     //ignore multiple clicks
250     if (changePasswordDialogStarted)
251     {
252         qDebug() << Q_FUNC_INFO << "Change password dialog is started already";
253         return;
254     }
255
256     changePasswordDialogStarted = true;
257
258     CredentialDialog *credentialDialog = new CredentialDialog(account->credentialsId());
259     if (!credentialDialog) {
260         qCritical() << "Cannot create change password dialog";
261         return;
262     }
263     credentialDialog->setParent(this);
264     connect (credentialDialog, SIGNAL(safeToDeleteMe(CredentialDialog*)),
265              this, SLOT(deleteCredentialsDialog()));
266     //% "Change Password"
267     credentialDialog->setTitle(qtTrId("qtn_acc_login_title_change"));
268     credentialDialog->exec();
269 }
270
271 void AccountSettingsPagePrivate::deleteCredentialsDialog()
272 {
273     changePasswordDialogStarted = false;
274     CredentialDialog *credentialDialog;
275
276     if (sender() != NULL &&
277         (credentialDialog = qobject_cast<CredentialDialog *>(sender())) != NULL)
278         credentialDialog->deleteLater();
279 }
280
281
282 /*
283  * The same serviceTypes cannot be enabled in meantime
284  * */
285 void AccountSettingsPagePrivate::disableSameServiceTypes(const QString &serviceType)
286 {
287     qDebug() << Q_FUNC_INFO << __LINE__;
288     if (!sender())
289     {
290         qCritical() << "disableSameServiceTypes() must be called via signaling";
291         return;
292     }
293
294     if (settingsWidgets.count(serviceType) == 1)
295         return;
296
297     foreach (ServiceSettingsWidget *widget, settingsWidgets.values(serviceType)) {
298         if (widget == sender())
299             continue;
300
301         widget->setServiceButtonEnable(false);
302     }
303 }
304
305 void AccountSettingsPagePrivate::setEnabledService(const QString &serviceName,
306                                                    bool enabled)
307 {
308     serviceStatusMap[serviceName] = enabled;
309 }
310
311 void AccountSettingsPagePrivate::scaleImage(const QImage &image, QImage &scaledImage)
312 {
313     qDebug() << "Org width/ height" << image.width() << image.height();
314     if (image.width() > preferredWidth
315         || image.height() > preferredHeight) {
316         qDebug() << "The loaded image needs scaling DOWN";
317         scaledImage = image.scaled(preferredWidth, preferredHeight,
318                                    Qt::KeepAspectRatio, Qt::SmoothTransformation);
319     } else {
320         qDebug() << "The loaded image needs scaling UP";
321         scaledImage = image.scaled(preferredWidth, preferredHeight,
322                                    Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
323     }
324
325 }
326
327 void AccountSettingsPagePrivate::setAvatarImage(const QImage &scaledImg)
328 {
329     QSize preferredSize(preferredWidth, preferredHeight);
330     QPixmap *maskPixmap = MTheme::pixmapCopy(QLatin1String("meegotouch-contactsui-avatar-mask"),
331                                              preferredSize);
332
333     QPixmap *framePixmap = MTheme::pixmapCopy(QLatin1String("meegotouch-contactsui-avatar-frame"),
334                                               preferredSize);
335
336     if (maskPixmap != NULL && framePixmap != NULL) {
337
338         qDebug() << "Non null Mask Pixmap && frame pixmap";
339         QImage maskImage = maskPixmap->toImage();
340         QImage frameImage = framePixmap->toImage();
341
342         QImage compositeImage(preferredSize, QImage::Format_ARGB32_Premultiplied);
343
344         QPainter painter(&compositeImage);
345         painter.setCompositionMode(QPainter::CompositionMode_Source);
346         painter.drawImage(0, 0, scaledImg);
347
348         painter.setCompositionMode(QPainter::CompositionMode_DestinationOut);
349         painter.drawImage(0, 0, maskImage);
350
351         painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
352         painter.drawImage(0, 0, frameImage);
353         painter.end();
354
355         avatarItem->setImage(compositeImage);
356
357         delete maskPixmap;
358         delete framePixmap;
359
360     } else {
361         avatarItem->setImage(scaledImg);
362     }
363 }
364
365 AccountSettingsPage::AccountSettingsPage(AbstractAccountSetupContext *context)
366         : MApplicationPage(),
367           d_ptr(new AccountSettingsPagePrivate(context))
368 {
369     Q_D(AccountSettingsPage);
370
371     Q_ASSERT (context != NULL);
372     d->q_ptr = this;
373
374     setStyleName("AccountsUiPage");
375     pannableViewport()->positionIndicator()->setStyleName("CommonPositionIndicatorInverted");
376 }
377
378 AccountSettingsPage::~AccountSettingsPage()
379 {
380     delete d_ptr;
381 }
382
383 void AccountSettingsPage::setServicesToBeShown()
384 {
385     qDebug() << Q_FUNC_INFO << "Deprecated. This function does nothing.";
386 }
387
388 QGraphicsLayoutItem *AccountSettingsPage::createServiceSettingsLayout()
389 {
390     Q_D(AccountSettingsPage);
391
392     MWidget *serviceWidget = new MWidget(this);
393     MLayout *serviceSettingLayout = new MLayout(serviceWidget);
394     serviceSettingLayout->setContentsMargins(0, 0, 0, 0);
395     MLinearLayoutPolicy *layoutServicePolicy =
396         new MLinearLayoutPolicy(serviceSettingLayout, Qt::Vertical);
397     layoutServicePolicy->setSpacing(0);
398
399     /* List the services available on the account and load all the respective plugins. */
400
401     //% "%1 Settings"
402     setTitle(qtTrId("qtn_acc_ser_prof_set_title").arg(d->context->account()->providerName()));
403
404     /* iterate through the contexts we created for each service, and get the
405      * UI widgets to embed */
406     QMap<QString, bool> enabledServiceTypes;
407
408     foreach (AbstractServiceSetupContext *context, d->contexts) {
409         d->abstractContexts.append(context);
410         const Accounts::Service *service = context->service();
411         ServiceSettingsWidget *settingsWidget;
412
413         d->account->selectService(service);
414         d->serviceStatusMap.insert(service->name(), d->account->enabled());
415         emit serviceEnabled(service->name(), d->account->enabled());
416         bool enabled = false;
417         if (d->account->enabled() &&
418             !enabledServiceTypes.contains(service->serviceType())) {
419             enabledServiceTypes.insert(service->serviceType(), true);
420             enabled = true;
421         }
422
423         int settingsConf =  ServiceSettingsWidget::EnableButton;
424         if (d->hasSingleService()) {
425            settingsConf = ServiceSettingsWidget::MandatorySettings
426                         | ServiceSettingsWidget::NonMandatorySettings;
427         }
428
429         settingsWidget = new ServiceSettingsWidget(
430             context, d->panel, settingsConf, enabled);
431         d->settingsWidgets.insertMulti(service->serviceType(), settingsWidget);
432
433         d->panelPolicy->addItem(settingsWidget);
434     }
435
436     d->panelPolicy->setSpacing(0);
437     layoutServicePolicy->addItem(d->panel);
438     /*
439      * no need in extra processing of any signals during content creation
440      * */
441
442     foreach (ServiceSettingsWidget *settingsWidget, d->settingsWidgets) {
443         connect(settingsWidget, SIGNAL(serviceButtonEnabled(const QString&)),
444                 d, SLOT(disableSameServiceTypes(const QString&)));
445         connect(settingsWidget, SIGNAL(serviceEnabled(const QString&, bool)),
446                 d, SIGNAL(serviceEnabled(const QString&, bool)));
447         connect(settingsWidget, SIGNAL(serviceEnabled(const QString&, bool)),
448                 d, SLOT(setEnabledService(const QString&, bool)));
449     }
450
451     return serviceWidget;
452 }
453
454 QGraphicsLayoutItem *AccountSettingsPage::createAccountSettingsLayout()
455 {
456     Q_D(AccountSettingsPage);
457
458     // First, see if the plugin has own implementation of this widget
459     QGraphicsLayoutItem *accountSettingsWidget = d->context->widget();
460     if (accountSettingsWidget != 0)
461         return accountSettingsWidget;
462
463     // Generic implementation
464     MWidget *upperWidget = new MWidget(this);
465     MLayout *upperLayout = new MLayout(upperWidget);
466     upperLayout->setContentsMargins(0, 0, 0, 0);
467     MLinearLayoutPolicy *upperLayoutPolicy =
468         new MLinearLayoutPolicy(upperLayout, Qt::Vertical);
469     upperLayoutPolicy->setSpacing(0);
470
471     MLayout *horizontalLayout = new MLayout();
472     horizontalLayout->setContentsMargins(0, 0, 0, 0);
473     MLinearLayoutPolicy *horizontalLayoutPolicy =
474         new MLinearLayoutPolicy(horizontalLayout, Qt::Horizontal);
475     horizontalLayoutPolicy->setSpacing(0);
476
477     QString providerName(d->account->providerName());
478     QString providerIconId;
479     QString providerTitleId;
480     Accounts::Provider *provider =
481         AccountsManager::instance()->provider(providerName);
482     if (provider) {
483         providerIconId = provider->iconName();
484         providerTitleId = provider->displayName();
485         QString catalog = provider->trCatalog();
486         MLocale locale;
487         if (!catalog.isEmpty() && !locale.isInstalledTrCatalog(catalog)) {
488             locale.installTrCatalog(catalog);
489             MLocale::setDefault(locale);
490         }
491     }
492
493     BasicHeaderWidget *usernameAndStatus = new BasicHeaderWidget(BasicHeaderWidget::IconWithTitleAndSubTitle, this);
494     usernameAndStatus->createLayout();
495     usernameAndStatus->setImage(providerIconId);
496     usernameAndStatus->setTitle(qtTrId(providerTitleId.toLatin1()));
497     usernameAndStatus->setSubtitle(d->account->displayName());
498
499     d->enableButton = new MButton(this);
500     d->enableButton->setViewType(MButton::switchType);
501     d->enableButton->setStyleName("CommonRightSwitchInverted");
502     d->enableButton->setCheckable(true);
503
504     d->account->selectService(NULL);
505     if (d->account->enabled()) {
506         d->panel->setEnabled(true);
507         d->enableButton->setChecked(true);
508     } else {
509         d->panel->setEnabled(false);
510         d->enableButton->setChecked(false);
511     }
512
513     connect(d->enableButton, SIGNAL(toggled(bool)), this, SLOT(enable(bool)));
514
515     horizontalLayoutPolicy->addItem(usernameAndStatus,
516                                     Qt::AlignLeft | Qt::AlignVCenter);
517     horizontalLayoutPolicy->addItem(d->enableButton,
518                                     Qt::AlignRight | Qt::AlignVCenter);
519
520     MWidgetController *spacer = new MWidgetController(this);
521     spacer->setStyleName("CommonSpacer");
522     upperLayoutPolicy->addItem(spacer);
523
524     upperLayoutPolicy->addItem(horizontalLayout);
525
526     spacer = new MWidgetController(this);
527     spacer->setStyleName("CommonSmallSpacer");
528     upperLayoutPolicy->addItem(spacer);
529
530     if (d->serviceList.count() <= 1) {
531         if ((d->contexts.at(0) != 0) && (d->contexts.at(0)->widget())) {
532             MSeparator *separatorTop = new MSeparator(this);
533             separatorTop->setOrientation(Qt::Horizontal);
534             separatorTop->setStyleName("CommonHeaderDividerInverted");
535             upperLayoutPolicy->addItem(separatorTop);
536         }
537     } else {
538         MSeparator *separatorTop = new MSeparator(this);
539         separatorTop->setOrientation(Qt::Horizontal);
540         separatorTop->setStyleName("CommonHeaderDividerInverted");
541         upperLayoutPolicy->addItem(separatorTop);
542     }
543
544     spacer = new MWidgetController(this);
545     spacer->setStyleName("CommonSmallSpacer");
546     upperLayoutPolicy->addItem(spacer);
547
548     struct system_config *sc = 0;
549     QByteArray name;
550
551     if (sysinfo_init(&sc) == 0) {
552         uint8_t *data = 0;
553         unsigned long size = 0;
554
555         if (sysinfo_get_value(sc, "/device/sw-release-ver",
556                               &data, &size) == 0) {
557             name = QByteArray((const char *)(data), size);
558             free(data);
559         }
560         sysinfo_finish(sc);
561     }
562
563     if (provider) {
564         QDomElement root = provider->domDocument().documentElement();
565         d->avatar = root.firstChildElement("display-avatar");
566
567         if (name.endsWith("003"))
568             d->avatar.clear();
569
570         if (d->avatar.text() == "true") {
571             d->avatarItem = new AvatarListItem();
572             connect(d->avatarItem, SIGNAL(clicked()), this, SLOT(changeAvatar()));
573             //% Avatar
574             d->avatarItem->setTitle(qtTrId("qtn_acc_avatar"));
575             d->panelPolicy->addItem(d->avatarItem);
576             d->avatarSelector = new AvatarSelector();
577         }
578     }
579
580     return upperWidget;
581 }
582
583
584 void AccountSettingsPage::getAvatar()
585 {
586     Q_D(AccountSettingsPage);
587     qDebug() << Q_FUNC_INFO;
588
589     if (d->accountPtr->isReady(d->accountFeatures)) {
590         Tp::Avatar accountAvatar = d->accountPtr->avatar();
591         d->avatarImageData = accountAvatar.avatarData;
592         d->avatarImageType = accountAvatar.MIMEType;
593
594         if (d->avatarImageData.isEmpty()) {
595             qDebug() << "Got a NULL Avatar image";
596             QMetaObject::invokeMethod(this, "requestAvatarData", Qt::QueuedConnection);
597         } else {
598             qDebug() << "Found  a proper image with type" << d->avatarImageType;
599         }
600         connect((Tp::Account *)d->accountPtr.data(), SIGNAL(avatarChanged(const Tp::Avatar &)),
601                 d, SLOT(onAvatarChange(const Tp::Avatar &)));
602         if (!d->avatarImageData.isEmpty()) {
603             const char *fmt = NULL;
604             if (d->avatarImageType.contains("jpeg", Qt::CaseInsensitive)
605                     || d->avatarImageType.contains("jpg", Qt::CaseInsensitive)) {
606                 qDebug() << "JPG format";
607                 fmt = "JPG";
608             }
609
610             QImage img;
611             img.loadFromData(d->avatarImageData, fmt);
612             d->saveImage(img);
613             qDebug() << "Received  a proper image with type" << d->avatarImageType;
614         } else {
615             d->avatarItem->setImage("icon-m-telephony-avatar-placeholder");
616             qDebug() << "Received a  NULL Avatar image";
617         }
618
619     } else {
620         qDebug() << "cannot get avatar";
621     }
622 }
623
624 void AccountSettingsPagePrivate::onAvatarChange(const Tp::Avatar &avatar)
625 {
626     qDebug() << Q_FUNC_INFO;
627     avatarImageData = avatar.avatarData;
628     avatarImageType = avatar.MIMEType;
629
630     if (!avatarImageData.isEmpty()) {
631         const char *fmt = NULL;
632         if (avatarImageType.contains("jpeg", Qt::CaseInsensitive) || avatarImageType.contains("jpg", Qt::CaseInsensitive)) {
633             qDebug() << "JPG format";
634             fmt = "JPG";
635         }
636
637         QImage img;
638         img.loadFromData(avatarImageData, fmt);
639         avatarItem->setImage(img);
640         qDebug() << "Received  a proper image with type" << avatarImageType;
641     } else {
642         qDebug() << "Received a  NULL Avatar image";
643     }
644 }
645
646 void AccountSettingsPagePrivate::onAccountManagerReady(Tp::PendingOperation *op)
647 {
648     Q_Q(AccountSettingsPage);
649     if (op->isError()) {
650         qDebug() << "Account Manager cannot become ready";
651         emit q->avatarInitFailed();
652     } else {
653         bool accFound = false;
654
655         QList<Tp::AccountPtr> givenProviderAccounts = accountMgr->allAccounts();
656         int numOfAccounts = givenProviderAccounts.count();
657         if (numOfAccounts == 0) {
658             qDebug() << "CANNOT GET EVEN ONE ACCOUNT";
659             emit q->avatarInitFailed();
660             return;
661         }
662
663         for (int i = 0; i < numOfAccounts; i++) {
664             Tp::AccountPtr acc = givenProviderAccounts[i];
665             qDebug() << "Retrieved account object path" << acc->objectPath() << "account bus name" << acc->busName()
666                     << "Retrieved account display name" << acc->displayName()
667                     << "Retrieved account nickname" << acc->nickname()
668                     << "tmc Account Path" << accountPath;
669             if (acc->objectPath() == accountPath) {
670                 qDebug() << "Found the right account";
671                 accountPtr = acc;
672                 accFound = true;
673                 break;
674             }
675         }
676         bool isValid = false;
677         if (accountPtr)
678             isValid =  accountPtr->isValid();
679         if (accFound && isValid) {
680             connect(accountPtr->becomeReady(accountFeatures),
681                     SIGNAL(finished(Tp::PendingOperation *)), this, SLOT(accountReady(Tp::PendingOperation *)));
682         }
683         if (!isValid)
684             qDebug() << "Account Not Valid";
685     }
686 }
687
688 void AccountSettingsPagePrivate::accountReady(Tp::PendingOperation *op)
689 {
690     Q_Q(AccountSettingsPage);
691     if (op->isError()) {
692         qDebug() << "Account could not become ready" << op->errorMessage() << op->errorName();
693         emit q->avatarInitFailed();
694         return;
695     }
696
697     qDebug() << "Account Ready";
698     emit q->avatarInitCompleted();
699 }
700
701 void AccountSettingsPage::createPageActions()
702 {
703     Q_D(AccountSettingsPage);
704     MAction *action;
705
706     //% "Save"
707     action = new MAction(qtTrId("qtn_comm_save"), this);
708     action->setLocation(MAction::ToolBarLocation);
709     addAction(action);
710     connect(action, SIGNAL(triggered()),
711             d, SLOT(saveSettings()));
712
713     //% "Cancel"
714     action = new MAction(qtTrId("qtn_comm_cancel"), this);
715     action->setLocation(MAction::ToolBarLocation);
716     addAction(action);
717     connect(action, SIGNAL(triggered()),
718             ProviderPluginProcess::instance(), SLOT(quit()));
719
720     // Hide the standard back/close button
721     setComponentsDisplayMode(MApplicationPage::EscapeButton,
722                              MApplicationPageModel::Hide);
723
724     //% "Delete"
725     action = new MAction(qtTrId("qtn_comm_command_delete"), this);
726     action->setLocation(MAction::ApplicationMenuLocation);
727     addAction(action);
728     connect(action, SIGNAL(triggered()),
729             this, SLOT(removeAccount()));
730 }
731
732 void AccountSettingsPage::createContent()
733 {
734     Q_D(AccountSettingsPage);
735
736     if (d->context == 0) return;
737
738     //we need a central widget to get the right layout size under the menubar
739     MWidget *centralWidget = new MWidget();
740     d->layout = new MLayout(centralWidget);
741     d->layout->setContentsMargins(0, 0, 0, 0);
742     MLinearLayoutPolicy *layoutPolicy =
743         new MLinearLayoutPolicy(d->layout, Qt::Vertical);
744     layoutPolicy->setSpacing(0);
745
746     MLayout *layoutPanel = new MLayout(d->panel);
747     layoutPanel->setContentsMargins(0, 0, 0, 0);
748     d->panelPolicy = new MLinearLayoutPolicy(layoutPanel, Qt::Vertical);
749
750     ServiceModel *serviceModel = new ServiceModel(d->context->account(), this);
751     SortServiceModel *sortModel = new SortServiceModel(this);
752     sortModel->setSourceModel(serviceModel);
753     sortModel->setEnabledServices(d->context->account()->enabledServices());
754     sortModel->setHiddenServices(d->hiddenServiceList);
755     sortModel->sort(ServiceModel::ServiceNameColumn);
756
757     d->contexts = ServiceModel::createServiceContexts(sortModel, d->context, this);
758     QGraphicsLayoutItem *accountSettingsLayout = createAccountSettingsLayout();
759     layoutPolicy->addItem(accountSettingsLayout);
760
761     QGraphicsLayoutItem *serviceWidget = createServiceSettingsLayout();
762     layoutPolicy->addItem(serviceWidget);
763
764     layoutPolicy->addStretch();
765
766     setCentralWidget(centralWidget);
767
768     createPageActions();
769     QString path;
770     if (d->avatar.text() == "true") {
771         Tp::registerTypes();
772         Tp::enableDebug(false);
773         Tp::enableWarnings(true);
774         foreach (AbstractServiceSetupContext *context, d->contexts) {
775             d->abstractContexts.append(context);
776             const Accounts::Service *service = context->service();
777             d->account->selectService(service);
778             d->accountPath = d->account->valueAsString("tmc-uid");
779             if (path.isNull()) {
780                 path = d->accountPath;
781             }
782         }
783         if (!path.contains("/org/freedesktop/Telepathy/Account/"))
784             path.prepend("/org/freedesktop/Telepathy/Account/");
785         d->accountPath = path;
786         d->accountMgr = Tp::AccountManager::create();
787         if (!d->accountMgr.isNull()) {
788             connect((d->accountMgr->becomeReady(Tp::AccountManager::FeatureCore)),
789                     SIGNAL(finished(Tp::PendingOperation *)), d,
790                     SLOT(onAccountManagerReady(Tp::PendingOperation *)));
791
792             QSet<Tp::Feature> featuresSet;
793             featuresSet << Tp::Account::FeatureAvatar;
794             d->accountFeatures = Tp::Features(featuresSet);
795             connect(this, SIGNAL(avatarInitCompleted()), this, SLOT(getAvatar()));
796             connect(this, SIGNAL(avatarInitFailed()), this, SLOT(initFailed()));
797         }
798     }
799 }
800
801 const AbstractAccountSetupContext *AccountSettingsPage::context()
802 {
803     Q_D(AccountSettingsPage);
804     return d->context;
805 }
806
807 void AccountSettingsPage::enable(bool state)
808 {
809     Q_D(AccountSettingsPage);
810     d->panel->setEnabled(state);
811 }
812
813 void AccountSettingsPage::removeAccount()
814 {
815     Q_D(AccountSettingsPage);
816     //% "Delete %1 from your device?"
817     QString dialogTitle =
818         qtTrId("qtn_acc_remove_account").arg(d->context->account()->displayName());
819     //% "All content related to this account will be deleted permanently"
820     MMessageBox removeMBox(dialogTitle, qtTrId("qtn_acc_remove_account_statement"),
821                            M::YesButton | M::NoButton);
822     removeMBox.setStyleName("RemoveDialog");
823
824     if (removeMBox.exec() == M::YesButton) {
825         d->context->account()->remove();
826         d->context->account()->sync();
827         ProviderPluginProcess::instance()->quit();
828     }
829 }
830
831 void AccountSettingsPage::setWidget(MWidget *widget)
832 {
833      Q_D(AccountSettingsPage);
834      d->panelPolicy->addItem(widget);
835 }
836
837 void AccountSettingsPage::setHiddenServices(const Accounts::ServiceList &hiddenServices)
838 {
839     Q_D(AccountSettingsPage);
840     d->hiddenServiceList = hiddenServices;
841 }
842
843 MButton *AccountSettingsPage::enableAccountButton() const
844 {
845     Q_D(const AccountSettingsPage);
846     return d->enableButton;
847 }
848
849 AccountSyncHandler *AccountSettingsPage::accountSyncHandler() const
850 {
851     Q_D(const AccountSettingsPage);
852     return d->syncHandler;
853 }
854
855 void AccountSettingsPage::changeAvatar()
856 {
857     Q_D(const AccountSettingsPage);
858     qDebug() << Q_FUNC_INFO;
859     d->avatarSelector->init();
860     connect(d->avatarSelector, SIGNAL(avatarSelected(const QImage &)),
861             d, SLOT(onAvatarSelectedFromGallery(const QImage &)));
862     d->avatarSelector->launch();
863 }
864
865 void AccountSettingsPagePrivate::onAvatarSelectedFromGallery(const QImage &image)
866 {
867     qDebug() << Q_FUNC_INFO;
868     disconnect(avatarSelector, SIGNAL(avatarSelected(const QImage &)),
869                this, SLOT(onAvatarSelectedFromGallery(const QImage &)));
870     saveImage(image);
871 }
872
873 void AccountSettingsPagePrivate::saveImage(const QImage &image)
874 {
875     qDebug() << Q_FUNC_INFO;
876
877     if (!image.isNull()) {
878
879         qDebug() << "Received image" << image.width() << image.height();
880         QImage scaledImg;
881         scaleImage(image, scaledImg);
882
883         if (!scaledImg.isNull()) {
884             setAvatarImage(scaledImg);
885             QByteArray rawData;
886             QBuffer buff(&rawData);
887             buff.open(QIODevice::WriteOnly);
888             if (scaledImg.save(&buff, "JPG")) {
889                 qDebug() << "Writing to ByteArray succesful" << rawData.size();
890                 avatarImageData = rawData;
891                 avatarImageType = "image/jpeg";
892             }
893         }
894     } else {
895         qDebug() << "NULL image from Gallery";
896     }
897 }