sync widget still not in accounts-ui
[accounts-sso:libaccounts-ui.git] / lib / AccountsUI / accountsettingspage.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 "accountsettingspage.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 "account-sync-handler.h"
31
32 //Accounts
33 #include <Accounts/Account>
34 #include <Accounts/Provider>
35
36 //Meegotouch
37 #include <MContainer>
38 #include <MLayout>
39 #include <MLinearLayoutPolicy>
40 #include <MMessageBox>
41 #include <MLocale>
42 #include <MAction>
43 #include <MLabel>
44 #include <MGridLayoutPolicy>
45 #include <MButton>
46 #include <MContentItem>
47 #include <MApplicationIfProxy>
48 #include <MContentItem>
49 #include <MSeparator>
50 #include <MImageWidget>
51
52 //Qt
53 #include <QDebug>
54 #include <QTimer>
55 #include <QMultiMap>
56
57 //Accounts-Ui
58 #include "abstract-account-setup-context.h"
59 #include "accountsmanagersingleton.h"
60
61 //sync-widget
62 #include "AccountsSyncWidget.h"
63
64 #define INFO_BANNER_TIMEOUT 3000
65
66 namespace AccountsUI {
67
68 class AccountSettingsPagePrivate
69 {
70 public:
71     AccountSettingsPagePrivate()
72             : context(0),
73             service(0),
74             account(0),
75             showAllServices(0),
76             usernameAndStatus(0),
77             serviceSettingLayout(0),
78             layoutServicePolicy(0),
79             enableButton(0),
80             syncHandler(0),
81             changePasswordDialogStarted(false)
82     {}
83
84     ~AccountSettingsPagePrivate() {}
85
86     AbstractAccountSetupContext *context;
87     const Accounts::Service *service;
88     Accounts::Account* account;
89     QList<AbstractServiceSetupContext *> contexts;
90     MAction *showAllServices;
91     MContentItem *usernameAndStatus;
92     QString serviceType;
93     MLayout *serviceSettingLayout;
94     MLinearLayoutPolicy *layoutServicePolicy;
95     MButton *enableButton;
96     Accounts::ServiceList serviceList;
97     QList<AbstractSetupContext*> abstractContexts;
98     AccountSyncHandler *syncHandler;
99     bool changePasswordDialogStarted;
100     QMultiMap<QString, ServiceSettingsWidget*> settingsWidgets;
101     MLayout *layout;
102     MLinearLayoutPolicy *layoutPolicy;
103 };
104
105 void AccountSettingsPage::setServicesToBeShown()
106 {
107     Q_D(AccountSettingsPage);
108     /* List the services available on the account and load all the respective plugins. */
109
110     //% "%1 Settings"
111     setTitle(qtTrId("qtn_acc_ser_prof_set_title").arg(d->context->account()->providerName()));
112
113     ServiceModel *serviceModel = new ServiceModel(d->context->account(), this);
114     SortServiceModel *sortModel = new SortServiceModel(this);
115     sortModel->setSourceModel(serviceModel);
116     sortModel->setEnabledServices(d->context->account()->enabledServices());
117     sortModel->sort(ServiceModel::ServiceNameColumn);
118
119     QAbstractProxyModel *proxy = 0;
120     // selecting the service type
121     if (!d->context->serviceType().isEmpty()) {
122         FilterTypeServiceModel *filterServiceModel = new FilterTypeServiceModel(this);
123         filterServiceModel->setSourceModel(sortModel);
124         filterServiceModel->setFilterFixedString(d->context->serviceType());
125         proxy = filterServiceModel;
126     } else
127         proxy = sortModel;
128
129     for (int i = 0; i < proxy->rowCount(); i++) {
130         QModelIndex index = proxy->index(i, 0);
131         const QVariant vServiceHelper = index.data(ServiceModel::ServiceHelperColumn);
132         ServiceHelper *serviceHelper = vServiceHelper.value<ServiceHelper *>();
133         AbstractServiceSetupContext *context =
134             serviceHelper->serviceSetupContext(d->context, this);
135         d->contexts.append(context);
136     }
137
138     /* iterate through the contexts we created for each service, and get the
139      * UI widgets to embed */
140     QMap<QString, bool> enabledServiceTypes;
141
142     foreach (AbstractServiceSetupContext *context, d->contexts) {
143         d->abstractContexts.append(context);
144         d->service = context->service();
145         const Accounts::Service *service = context->service();
146         ServiceSettingsWidget *settingsWidget;
147
148         d->account->selectService(service);
149
150         bool enabled = false;
151         if (d->account->enabled() &&
152             !enabledServiceTypes.contains(service->serviceType())) {
153             enabledServiceTypes.insert(service->serviceType(), true);
154             enabled = true;
155         }
156
157         if (d->serviceList.count() > 1)
158             settingsWidget = new ServiceSettingsWidget(context,
159                                                    this,
160                                                    ServiceSettingsWidget::EnableButton,
161                                                    enabled);
162         else
163             settingsWidget = new ServiceSettingsWidget(context,
164                                                        this,
165                                                        ServiceSettingsWidget::MandatorySettings |
166                                                        ServiceSettingsWidget::NonMandatorySettings,
167                                                        enabled);
168
169         d->settingsWidgets.insertMulti(service->serviceType(), settingsWidget);
170         d->layoutServicePolicy->addItem(settingsWidget);
171     }
172
173     /*
174      * no need in extra processing of any signals during content creation
175      * */
176     foreach (ServiceSettingsWidget *settingsWidget, d->settingsWidgets)
177         connect (settingsWidget, SIGNAL(serviceButtonEnabled(const QString&)),
178                  this, SLOT(disableSameServiceTypes(const QString&)));
179 }
180
181 AccountSettingsPage::AccountSettingsPage(AbstractAccountSetupContext *context)
182         : MApplicationPage(),
183           d_ptr(new AccountSettingsPagePrivate())
184 {
185     Q_D(AccountSettingsPage);
186
187     Q_ASSERT (context != NULL);
188     d->context = context;
189     d->account = d->context->account();
190     d->abstractContexts.append(d->context);
191     d->serviceType = d->context->serviceType();
192
193     d->syncHandler = new AccountSyncHandler(this);
194     connect(d->syncHandler, SIGNAL(syncStateChanged(const SyncState&)),
195             this, SLOT(onSyncStateChanged(const SyncState&)));
196     setStyleName("AccountSettingsPage");
197 }
198
199 AccountSettingsPage::~AccountSettingsPage()
200 {
201     delete d_ptr;
202 }
203
204 void AccountSettingsPage::createContent()
205 {
206     Q_D(AccountSettingsPage);
207
208     //we need a central widget to get the right layout size under the menubar
209     MWidget* centralWidget = new MWidget();
210     d->layout = new MLayout(centralWidget);
211     d->layoutPolicy = new MLinearLayoutPolicy(d->layout, Qt::Vertical);
212     d->layoutPolicy->setSpacing(0);
213
214     if (d->context) {
215         QGraphicsLayoutItem *accountSettingsWidget = d->context->widget();
216         d->serviceList = d->account->services();
217         if (accountSettingsWidget != 0) {
218             d->layoutPolicy->addItem(accountSettingsWidget);
219         } else {
220             MWidget *upperWidget = new MWidget(this);
221             MLayout *upperLayout = new MLayout(upperWidget);
222             MLinearLayoutPolicy *upperLayoutPolicy = new MLinearLayoutPolicy(upperLayout, Qt::Vertical);
223             upperLayoutPolicy->setSpacing(0);
224
225             MLayout *horizontalLayout = new MLayout();
226             MLinearLayoutPolicy *horizontalLayoutPolicy = new MLinearLayoutPolicy(horizontalLayout, Qt::Horizontal);
227             horizontalLayoutPolicy->setSpacing(0);
228
229             QString providerName(d->account->providerName());
230             QString providerIconId;
231             // xml file that describes the ui elements for the provider
232             Accounts::Provider *provider = AccountsManager::instance()->provider(providerName);
233             if (provider) {
234                 QDomElement root = provider->domDocument().documentElement();
235                 QDomElement providerIcon = root.firstChildElement("icon");
236                 providerIconId = providerIcon.text();
237             }
238
239             d->usernameAndStatus = new MContentItem(MContentItem::IconAndTwoTextLabels, this);
240             d->usernameAndStatus->setImageID(providerIconId);
241             d->usernameAndStatus->setTitle(providerName);
242             d->usernameAndStatus->setSubtitle(d->context->account()->displayName());
243
244             MSeparator *separatorTop = new MSeparator(this);
245             separatorTop->setOrientation(Qt::Horizontal);
246
247             d->serviceList = d->account->services();
248
249             d->enableButton = new MButton(this);
250             d->enableButton->setViewType(MButton::switchType);
251             d->enableButton->setCheckable(true);
252
253             d->account->selectService(NULL);
254             if ( d->account->enabled())
255                 d->enableButton->setChecked(true);
256             else
257                 d->enableButton->setChecked(false);
258
259             connect(d->enableButton, SIGNAL(toggled(bool)), this, SLOT(enable(bool)));
260
261             horizontalLayoutPolicy->addItem(d->usernameAndStatus, Qt::AlignLeft | Qt::AlignVCenter);
262             horizontalLayoutPolicy->addItem(d->enableButton, Qt::AlignRight | Qt::AlignVCenter);
263             upperLayoutPolicy->addItem(horizontalLayout);
264             upperLayoutPolicy->addItem(separatorTop);
265
266             d->layoutPolicy->addItem(upperWidget);
267         }
268     }
269
270     MWidget *serviceWidget = new MWidget(this);
271     d->serviceSettingLayout = new MLayout(serviceWidget);
272     d->layoutServicePolicy = new MLinearLayoutPolicy(d->serviceSettingLayout, Qt::Vertical);
273     d->layoutServicePolicy->setSpacing(0);
274
275     /* Sets the service widgets and add it into the layout policy*/
276     setServicesToBeShown();
277
278     QStringList servicesNames;
279     for (int i = 0; i < d->serviceList.count(); i++)
280         servicesNames << d->serviceList.at(i)->name();
281
282     /* sync widget */
283 //    AccountsSyncWidget *syncItem = new AccountsSyncWidget(d->account->id(), servicesNames);
284
285 //    QString catalog = syncItem->trCatalog();
286 //    if (!catalog.isEmpty()) {
287 //        MLocale locale;
288 //        locale.installTrCatalog(catalog);
289 //        MLocale::setDefault(locale);
290 //    }
291 //setWidget();
292
293 //    syncItem->createWidget();
294
295     setCentralWidget(centralWidget);
296
297     //% "Delete"
298     MAction *action = new MAction(QLatin1String("icon-m-toolbar-delete"),
299                                   qtTrId("qtn_comm_command_delete"), this);
300     action->setLocation(MAction::ToolBarLocation);
301     addAction(action);
302
303     connect(action, SIGNAL(triggered()),
304             this, SLOT(removeAccount()));
305
306     if (d->context && !d->context->serviceType().isEmpty()) {
307         QStringList serviceType;
308         Accounts::ServiceList services = d->context->account()->services();
309         foreach (Accounts::Service *service, services) {
310             serviceType.append(service->serviceType());
311         }
312         serviceType.removeDuplicates();
313         if (serviceType.count() > 1) {
314             //% "All Services"
315             d->showAllServices = new MAction(qtTrId("qtn_acc_settings_all_services"), this);
316             d->showAllServices->setLocation(MAction::ApplicationMenuLocation);
317             addAction(d->showAllServices);
318             connect(d->showAllServices, SIGNAL(triggered()),
319                     this, SLOT(showAllServices()));
320         }
321     }
322
323     MSeparator *separatorBottom = new MSeparator(this);
324     separatorBottom->setOrientation(Qt::Horizontal);
325
326     d->layoutPolicy->addItem(serviceWidget);
327     d->layoutPolicy->addItem(separatorBottom);
328 //    if (syncItem->mustBeShown())
329 //        d->layoutPolicy->addItem(syncItem);
330     d->layoutPolicy->addStretch();
331
332     //Saving the settings on back button press
333     connect(this, SIGNAL(backButtonClicked()),
334             this, SLOT(saveSettings()));
335 }
336
337 const AbstractAccountSetupContext *AccountSettingsPage::context()
338 {
339     Q_D(AccountSettingsPage);
340     return d->context;
341 }
342
343 void AccountSettingsPage::enable(bool state)
344 {
345     Q_D(AccountSettingsPage);
346
347     if (d->serviceList.count() == 1) {
348         d->account->selectService(d->serviceList.at(0));
349         d->account->setEnabled(state);
350     }
351
352     d->context->account()->selectService(NULL);
353     if (state) {
354         if (d->usernameAndStatus)
355             d->usernameAndStatus->setSubtitle(QString::null);
356     } else {
357         if (d->usernameAndStatus)
358             //TODO: as the qtn_acc_disabled is removed we are still waiting how we show disabled account
359             d->usernameAndStatus->setSubtitle(QLatin1String("Disabled"));
360     }
361
362     d->account->setEnabled(state);
363 }
364
365 void AccountSettingsPage::removeAccount()
366 {
367     Q_D(AccountSettingsPage);
368     //% "Delete %1 from your device?"
369     QString dialogTitle =
370         qtTrId("qtn_acc_remove_account").arg(d->context->account()->displayName());
371     MMessageBox removeMBox(dialogTitle, M::YesButton | M::NoButton);
372     removeMBox.setStyleName("RemoveDialog");
373
374     if (removeMBox.exec() == M::YesButton) {
375         d->context->account()->remove();
376         d->context->account()->sync();
377         ProviderPluginProcess::instance()->quit();
378     }
379 }
380
381 void AccountSettingsPage::saveSettings()
382 {
383     Q_D(AccountSettingsPage);
384     setProgressIndicatorVisible(true);
385     qDebug() << Q_FUNC_INFO;
386
387     //we should call only validate. Storing will be handled
388     //in onSyncStateChangted func.
389     d->syncHandler->validate(d->abstractContexts);
390 }
391
392 void AccountSettingsPage::onSyncStateChanged(const SyncState &state)
393 {
394     qDebug() << Q_FUNC_INFO;
395
396     Q_D(AccountSettingsPage);
397     switch (state) {
398         case NotValidated:
399             qDebug() << Q_FUNC_INFO << "NotValidated";
400             setProgressIndicatorVisible(false);
401             break;
402         case Validated:
403             qDebug() << Q_FUNC_INFO << "Validated";
404             d->syncHandler->store(d->abstractContexts);
405             break;
406         case NotStored:
407             qDebug() << Q_FUNC_INFO << "NotStored";
408             connect(d->context->account(), SIGNAL(synced()),
409                     ProviderPluginProcess::instance(), SLOT(quit()));
410             d->context->account()->sync();
411             break;
412         case Stored:
413             qDebug() << Q_FUNC_INFO << "Stored";
414             connect(d->context->account(), SIGNAL(synced()),
415                     ProviderPluginProcess::instance(), SLOT(quit()));
416             d->context->account()->sync();
417             break;
418         default:
419             return;
420     }
421 }
422
423 void AccountSettingsPage::openChangePasswordDialog()
424 {
425     Q_D(AccountSettingsPage);
426     //ignore multiple clicks
427     if (d->changePasswordDialogStarted)
428     {
429         qDebug() << Q_FUNC_INFO << "Change password dialog is started already";
430         return;
431     }
432
433     d->changePasswordDialogStarted = true;
434
435     CredentialDialog *credentialDialog = new CredentialDialog(d->account->credentialsId());
436     credentialDialog->setParent(this);
437
438     if (!credentialDialog) {
439         qCritical() << "Cannot create change password dialog";
440         return;
441     }
442     connect (credentialDialog, SIGNAL(safeToDeleteMe(CredentialDialog*)),
443              this, SLOT(deleteCredentialsDialog()));
444     //% "Change Password"
445     credentialDialog->setTitle(qtTrId("qtn_acc_login_title_change"));
446     credentialDialog->exec();
447 }
448
449 void AccountSettingsPage::deleteCredentialsDialog()
450 {
451     Q_D(AccountSettingsPage);
452     d->changePasswordDialogStarted = false;
453     CredentialDialog *credentialDialog;
454
455     if (sender() != NULL &&
456         (credentialDialog = qobject_cast<CredentialDialog *>(sender())) != NULL)
457         credentialDialog->deleteLater();
458 }
459
460 void AccountSettingsPage::showAllServices()
461 {
462     Q_D(AccountSettingsPage);
463     d->serviceType = QLatin1String("");
464     setServicesToBeShown();
465     d->showAllServices->setVisible(false);
466 }
467
468
469 /*
470  * The same serviceTypes cannot be enabled in meantime
471  * */
472 void AccountSettingsPage::disableSameServiceTypes(const QString &serviceType)
473 {
474     Q_D(AccountSettingsPage);
475     qDebug() << Q_FUNC_INFO << __LINE__;
476     if (!sender())
477     {
478         qCritical() << "disableSameServiceTypes() must be called via signaling";
479         return;
480     }
481
482     if (d->settingsWidgets.count(serviceType) == 1)
483         return;
484
485     foreach (ServiceSettingsWidget *widget, d->settingsWidgets.values(serviceType)) {
486         if (widget == sender())
487             continue;
488
489         widget->setServiceButtonEnable(false);
490     }
491 }
492
493 void AccountSettingsPage::setWidget(MWidget *widget)
494 {
495      Q_D(AccountSettingsPage);
496      d->layoutPolicy->addItem(widget);
497 }
498
499 } // namespace