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