main.cpp 17.8 KB
Newer Older
1
/*
2
 * Copyright (C) 2014-2018 CZ.NIC
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations including
 * the two.
 */

#include <QApplication>
25
#include <QCommandLineParser>
26
#include <QQmlApplicationEngine>
Martin Straka's avatar
Martin Straka committed
27
#include <QQuickStyle>
28 29 30 31 32 33 34
#include <QSettings>
#include <QTranslator>
#include <QtQuick>
#include <QtSvg>
#include <QtXml>

#include "src/accounts.h"
35
#include "src/datovka_shared/io/records_management_db.h"
36
#include "src/datovka_shared/localisation/localisation.h"
37 38
#include "src/dialogues/qml_dialogue_helper.h"
#include "src/dialogues/qml_input_dialogue.h"
39
#include "src/dialogues/dialogues.h"
40
#include "src/files.h"
41
#include "src/global.h"
42
#include "src/io/filesystem.h"
Karel Slaný's avatar
Karel Slaný committed
43
#include "src/locker.h"
44
#include "src/log/log.h"
45 46
#include "src/net/isds_wrapper.h"
#include "src/models/accountmodel.h"
47
#include "src/models/databoxmodel.h"
48
#include "src/models/filemodel.h"
49
#include "src/models/list_sort_filter_proxy_model.h"
50
#include "src/models/messagemodel.h"
51 52 53
#if defined(Q_OS_ANDROID)
#include "src/os_android.h"
#endif /* defined(Q_OS_ANDROID) */
Martin Straka's avatar
Martin Straka committed
54
#include "src/qml_interaction/attachment_data.h"
55
#include "src/qml_interaction/image_provider.h"
56
#include "src/qml_interaction/interaction_filesystem.h"
57
#include "src/qml_interaction/interaction_zfo_file.h"
Martin Straka's avatar
Martin Straka committed
58
#include "src/qml_interaction/message_envelope.h"
59
#include "src/qml_interaction/string_manipulation.h"
60
#include "src/records_management/models/upload_hierarchy_list_model.h"
61
#include "src/records_management/models/upload_hierarchy_qml_proxy_model.h"
62
#include "src/records_management.h"
63
#include "src/settings.h"
Martin Straka's avatar
Martin Straka committed
64
#include "src/setwrapper.h"
65 66 67
#include "src/sqlite/db_tables.h"
#include "src/sqlite/account_db.h"
#include "src/sqlite/file_db_container.h"
Martin Straka's avatar
Martin Straka committed
68 69
#include "src/sqlite/message_db_container.h"
#include "src/sqlite/zfo_db.h"
70
#include "src/worker/emitter.h"
71
#include "src/worker/pool.h"
72
#include "src/zfo.h"
73

74
/* iOS app_delegate - for interaction with iOS action Open in... */
75 76 77 78
#if defined Q_OS_IOS
#include "ios/src/qt_app_delegate.h"
#endif

79 80 81
/* ACCOUNT DB filename */
#define ACNT_DB_NAME "accounts.db"

82 83 84 85 86
/* APPLICATION IDENTIFICATION */
#define APP_ORG_NAME "CZ.NIC, z.s.p.o."
#define APP_ORG_DOMAIN "cz.nic"
#define DEFAULT_FONT_FAMILY "System"

87
/* namespace for QML registered objects */
88
const char *uri = "cz.nic.mobileDatovka"; /* Pages and components. */
89

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
/*!
 * @brief Used when registering types.
 */
struct QmlTypeEntry {
	const char *typeName;
	int major;
	int minor;
};

#define QML_PAGE_LOC "qrc:/qml/pages"
/*!
 * @brief NULL-terminated list of pages.
 */
static
const struct QmlTypeEntry qmlPages[] = {
Karel Slaný's avatar
Karel Slaný committed
105 106 107
	{ "PageAboutApp", 1, 0 },
	{ "PageAccountDetail", 1, 0 },
	{ "PageAccountList", 1, 0 },
108
	{ "PageChangePassword", 1, 0 },
Martin Straka's avatar
Martin Straka committed
109
	{ "PageContactList", 1, 0 },
110
	{ "PageDataboxDetail", 1, 0 },
111
	{ "PageDataboxSearch", 1, 0 },
Martin Straka's avatar
Martin Straka committed
112
	{ "PageImportMessage", 1, 0 },
Karel Slaný's avatar
Karel Slaný committed
113 114 115 116 117 118 119
	{ "PageMenuAccount", 1, 0 },
	{ "PageMenuDatovkaSettings", 1, 0 },
	{ "PageMenuMessage", 1, 0 },
	{ "PageMenuMessageDetail", 1, 0 },
	{ "PageMenuMessageList", 1, 0 },
	{ "PageMessageDetail", 1, 0 },
	{ "PageMessageList", 1, 0 },
120
	{ "PageMessageSearch", 1, 0 },
121
	{ "PageRecordsManagementUpload", 1, 0 },
122
	{ "PageSendMessage", 1, 0 },
Karel Slaný's avatar
Karel Slaný committed
123 124 125
	{ "PageSettingsAccount", 1, 0 },
	{ "PageSettingsGeneral", 1, 0 },
	{ "PageSettingsPin", 1, 0 },
126
	{ "PageSettingsRecordsManagement", 1, 0 },
Karel Slaný's avatar
Karel Slaný committed
127 128
	{ "PageSettingsStorage", 1, 0 },
	{ "PageSettingsSync", 1, 0 },
129
	{ NULL, 0, 0 }
130 131
};

132 133 134 135 136 137
#define QML_COMPONENT_LOC "qrc:/qml/components"
/*!
 * @brief NULL-terminated list of components.
 */
static
const struct QmlTypeEntry qmlComponents[] = {
138
	{ "AccessibleButton", 1, 0 },
139
	{ "AccessibleButtonWithImage", 1, 0 },
140
	{ "AccessibleComboBox", 1, 0 },
141
	{ "AccessibleImageButton", 1, 0 },
142
	{ "AccessibleMenu", 1, 0 },
143
	{ "AccessibleOverlaidImageButton", 1, 0 },
144
	{ "AccessibleSpinBox", 1, 0 },
145
	{ "AccessibleSpinBoxZeroMax", 1, 0 },
146
	{ "AccessibleSwitch", 1, 0 },
Karel Slaný's avatar
Karel Slaný committed
147
	{ "AccessibleTabButton", 1, 0 },
148
	{ "AccessibleText", 1, 0 },
149
	{ "AccessibleTextButton", 1, 0 },
150
	{ "AccessibleTextField", 1, 0 },
151
	{ "DataboxList", 1, 0 },
Karel Slaný's avatar
Karel Slaný committed
152
	{ "FilterBar", 1, 0 },
153
	{ "InputLineMenu", 1, 0 },
154
	{ "MessageList", 1, 0 },
155
	{ "OverlaidImage", 1, 0 },
Martin Straka's avatar
Martin Straka committed
156
	{ "PageHeader", 1, 0 },
157
	{ "ProgressBar", 1, 0 },
158
	{ "ScrollableListView", 1, 0 },
159 160 161
	{ NULL, 0, 0 }
};

162 163 164 165 166 167
#define QML_DIALOGUES "qrc:/qml/dialogues"
/*!
 * @brief NULL-terminated list of components.
 */
static
const struct QmlTypeEntry qmlDialogues[] = {
168
	{ "FileDialogue", 1, 0 },
Martin Straka's avatar
Martin Straka committed
169
	{ "InputDialogue", 1, 0},
170
	{ "MessageDialogue", 1, 0},
171 172 173 174
	{ "PasteInputDialogue", 1, 0 },
	{ NULL, 0, 0 }
};

175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
/*!
 * @brief Initialises command line parser.
 *
 * @param[in,out] parser Command line parser object to be initialised.
 * @return 0 on success, -1 on failure
 */
static
int setupCmdLineParser(QCommandLineParser &parser)
{
	parser.setApplicationDescription(QObject::tr("Data box application"));
	parser.addHelpOption();
	parser.addVersionOption();

	parser.addPositionalArgument("[zfo-file]",
	    QObject::tr("ZFO file to be viewed."));

	return 0;
}

194 195 196 197 198 199 200 201 202 203
/*!
 * @brief Registers QML types.
 *
 * @param[in] uri Namespace for QML objects.
 * @param[in] location Location of the QML description file.
 * @Param[in] entries List of entries describing the types.
 */
static
void registerQmlTypes(const char *uri, const char *location,
    const struct QmlTypeEntry *entries)
204
{
205 206 207 208 209 210 211 212 213 214 215 216 217
	if ((uri == NULL) || (location == NULL)) {
		Q_ASSERT(0);
		return;
	}

	const struct QmlTypeEntry *entry = entries;
	while ((entry != NULL) && (entry->typeName != NULL)) {
		qmlRegisterType(
		    QUrl(QString("%1/%2.qml").arg(location).arg(entry->typeName)),
		    uri, entry->major, entry->minor, entry->typeName);
		++entry;
	}
}
218

219 220
int main(int argc, char *argv[])
{
Martin Straka's avatar
Martin Straka committed
221 222
	QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
	QQuickStyle::setStyle("Material");
223
	//qputenv("QT_QUICK_CONTROLS_STYLE", "material");
224

Karel Slaný's avatar
Karel Slaný committed
225
	/* First thing to create is the application object. */
226 227 228 229 230 231
	QApplication app(argc, argv);
	/*
	 * This object needs to be created in the same thread as the
	 * application.
	 */
	QmlDlgHelper dlgHelper;
232
	QmlDlgHelper::dlgEmitter = &dlgHelper;
233

234 235 236 237 238 239 240 241
	/* Perform check that configuration file can be accessed. */
	const QString settingsFileName(Settings::settingsPath());
	if (settingsFileName.isEmpty()) {
		return EXIT_FAILURE;
	}

	QCoreApplication::addLibraryPath("./");

242 243 244
	/* Initialise random number generator. */
	qsrand(QDateTime::currentDateTimeUtc().toTime_t());

245
	/* set application data, identification, etc. */
246 247 248 249 250
	app.setOrganizationName(APP_ORG_NAME);
	app.setOrganizationDomain(APP_ORG_DOMAIN);
	app.setApplicationName(APP_NAME);
	app.setApplicationVersion(VERSION);

251 252 253 254 255 256 257 258
	QCommandLineParser parser;
	if (0 != setupCmdLineParser(parser)) {
		return EXIT_FAILURE;
	}

	/* Process command-line arguments. */
	parser.process(app);

259 260
	/* Create globally accessible objects. */
	{
261
		GlobInstcs::msgProcEmitterPtr =
262
		    new (std::nothrow) MessageProcessingEmitter;
263
		if (GlobInstcs::msgProcEmitterPtr == Q_NULLPTR) {
264 265 266 267 268 269 270 271 272 273
			qCritical("Cannot create status message emitter.");
			return EXIT_FAILURE;
		}
		/*
		 * Only one worker thread currently.
		 * TODO -- To be able to run multiple threads in the pool
		 * a locking mechanism over isds context structures must
		 * be implemented. Also, per-context queueing
		 * ought to be implemented to avoid unnecessary waiting.
		 */
274 275
		GlobInstcs::workPoolPtr = new (std::nothrow) WorkerPool(1);
		if (GlobInstcs::workPoolPtr == Q_NULLPTR) {
276 277 278 279
			qCritical("Cannot create worker pool.");
			return EXIT_FAILURE;
		}

280 281
		GlobInstcs::setPtr = new (std::nothrow) Settings;
		if (GlobInstcs::setPtr == Q_NULLPTR) {
282 283 284 285 286
			qCritical("cannot create settings.");
			return EXIT_FAILURE;
		}
	}

287 288
	QStringList cmdLineFileNames;
#if defined(Q_OS_ANDROID)
289
	cmdLineFileNames = IntentNotification::getIntentArguments();
290 291 292
#else
	cmdLineFileNames = parser.positionalArguments();
#endif /* defined(Q_OS_ANDROID) */
293

294 295 296 297
	/* load global settings */
	{
		QSettings settings(Settings::settingsPath(),
		    QSettings::IniFormat);
298
		GlobInstcs::setPtr->loadFromSettings(settings);
299 300
	}

301 302 303
	/* set font family and font size from settings */
	QFont font;
	font.setFamily(DEFAULT_FONT_FAMILY);
304
	font.setPointSize(GlobInstcs::setPtr->fontSize);
305 306
	app.setFont(font);

307 308 309
	/* load datovka localization and qtbase localization */
	QTranslator datovkaTrans;
	QTranslator qtbaseTrans;
310
	QString lang(
311 312
	    Localisation::shortLangName(GlobInstcs::setPtr->language));
	Localisation::setProgramLocale(GlobInstcs::setPtr->language);
313 314 315 316 317 318 319 320 321
	if (!datovkaTrans.load("datovka_" + lang, ":/locale/")) {
		qDebug() << "Could not load datovka localisation file...";
	}
	app.installTranslator(&datovkaTrans);
	if (!qtbaseTrans.load("qtbase_" + lang, ":/locale/")) {
		qDebug() << "Could not load qtbase localisation file...";
	}
	app.installTranslator(&qtbaseTrans);

322
	/* Start worker threads. */
323
	GlobInstcs::workPoolPtr->start();
324 325
	logInfoNL("%s", "Worker pool started.");

326 327 328 329 330 331
	/* Init and use these class - we need register it to QML */
	Messages messages;
	Accounts accounts;
	Files files;
	IsdsWrapper isds;
	GlobalSettingsQmlWrapper settings;
332
	RecordsManagement recordsManagement;
333
	StringManipulation strManipulation;
334
	Zfo zfo;
335 336 337 338 339

	/* Connect slot for isds cxt delete when account was deleted or updated */
	QObject::connect(&accounts, SIGNAL(removeIsdsCtx(QString)),
	    &isds, SLOT(removeIsdsCtx(QString)));

340 341 342 343 344 345 346
	/* Register application state changes. */
	class Locker locker;
	QObject::connect(&app,
	    SIGNAL(applicationStateChanged(Qt::ApplicationState)),
	    &locker, SLOT(processNewState(Qt::ApplicationState)));
	app.installEventFilter(&locker);

347
	/* Create and init account model. */
348 349
	AccountListModel *accountModelPtr = new (std::nothrow) AccountListModel;
	if (Q_NULLPTR == accountModelPtr) {
350 351 352
		qCritical("Cannot create account model.");
		return EXIT_FAILURE;
	}
353
	accountModelPtr->setObjectName("mainAccountModel");
354 355 356 357

	/* get main handle of appliaction and QML */
	QQmlApplicationEngine engine;
	QQmlContext *ctx = engine.rootContext();
358 359 360 361 362 363 364

	globImgProvPtr = new (std::nothrow) ImageProvider;
	if (Q_NULLPTR == globImgProvPtr) {
		qCritical("Cannot create image provider.");
		return EXIT_FAILURE;
	}
	engine.addImageProvider(IMAGE_PROVIDER_ID, globImgProvPtr);
365

366 367 368
	/* Register application pages to QML */
	registerQmlTypes(uri, QML_PAGE_LOC, qmlPages);
	registerQmlTypes(uri, QML_COMPONENT_LOC, qmlComponents);
369
	registerQmlTypes(uri, QML_DIALOGUES, qmlDialogues);
370

371
	/* Register types into QML. */
372
	AccountListModel::declareQML();
Martin Straka's avatar
Martin Straka committed
373
	AttachmentData::declareQML();
374
	DataboxListModel::declareQML();
375
	DataboxModelEntry::declareQML();
376
	Dialogues::declareQML();
377
	FileListModel::declareQML();
Martin Straka's avatar
Martin Straka committed
378
	Files::declareQML();
379
	InteractionFilesystem::declareQML();
380
	ListSortFilterProxyModel::declareQML();
381
	MessageListModel::declareQML();
382
	Messages::declareQML();
Martin Straka's avatar
Martin Straka committed
383
	MsgEnvelope::declareQML();
Martin Straka's avatar
Martin Straka committed
384
	MsgInfo::declareQML();
385
	UploadHierarchyListModel::declareQML();
386
	UploadHierarchyQmlProxyModel::declareQML();
387

388 389
	InteractionZfoFile interactionZfoFile;

390 391 392 393 394 395
	/* Inicialize app delegate component for interaction with iOS
	 * Reaction on the iOS action "Open in..." */
#if defined Q_OS_IOS
	QtAppDelegateInitialize(&interactionZfoFile);
#endif

396 397 398 399 400 401
	/* register classes in QML */
	ctx->setContextProperty("isds", &isds);
	ctx->setContextProperty("messages", &messages);
	ctx->setContextProperty("accounts", &accounts);
	ctx->setContextProperty("files", &files);
	ctx->setContextProperty("settings", &settings);
402
	ctx->setContextProperty("strManipulation", &strManipulation);
403
	ctx->setContextProperty("locker", &locker);
404
	ctx->setContextProperty("interactionZfoFile", &interactionZfoFile);
405
	ctx->setContextProperty("dlgEmitter", QmlDlgHelper::dlgEmitter);
406
	ctx->setContextProperty("zfo", &zfo);
407
	ctx->setContextProperty("recordsManagement", &recordsManagement);
408 409

	/* register and set models in QML */
410
	ctx->setContextProperty(accountModelPtr->objectName(), accountModelPtr);
411 412 413 414 415 416 417

	/* Localise description in tables. */
	accntinfTbl.reloadLocalisedDescription();
	userinfTbl.reloadLocalisedDescription();
	msgsTbl.reloadLocalisedDescription();
	flsTbl.reloadLocalisedDescription();
	evntsTbl.reloadLocalisedDescription();
Karel Slaný's avatar
Karel Slaný committed
418
	msgZfoTbl.reloadLocalisedDescription();
419

420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
	/* Init and open account database. */
	AccountDb accountDb("ACCOUNTS", false);
	MsgDbContainer messageDbs("MESSAGES");
	FileDbContainer fileDbs("FILES");
	ZfoDb zfoDb("ZFOS", false);

	{
		GlobInstcs::accountDbPtr = &accountDb;
		GlobInstcs::messageDbsPtr = &messageDbs;
		GlobInstcs::fileDbsPtr = &fileDbs;
		GlobInstcs::zfoDbPtr = &zfoDb;
		GlobInstcs::recMgmtDbPtr = new (std::nothrow)
		    RecordsManagementDb("recordsManagementDb", false);
		if (GlobInstcs::recMgmtDbPtr == Q_NULLPTR) {
			logErrorNL("%s",
			    "Cannot allocate records management db.");
			return EXIT_FAILURE;
		}
	}
439

440 441 442 443 444 445 446 447
	QString dirName(
	    existingWritableLocation(QStandardPaths::AppDataLocation));
	if (dirName.isEmpty()) {
		logErrorNL("%s",
		    "Cannot determine application data location.");
		Q_ASSERT(0);
		return EXIT_FAILURE;
	}
448

449
	QString dbPath(dirName + QDir::separator() + ACNT_DB_NAME);
450 451
	if (!GlobInstcs::accountDbPtr->openDb(dbPath,
	        SQLiteDb::CREATE_MISSING)) {
452 453
		logErrorNL("%s", "Account database not found!");
		return EXIT_FAILURE;
454 455
	}

456 457
	/* Open records management database. */
	QString rmDbPath(dirName + QDir::separator() + RECORDS_MANAGEMENT_DB_FILE);
458
	if (!GlobInstcs::recMgmtDbPtr->openDb(
459 460 461 462 463 464
	        rmDbPath, SQLiteDb::CREATE_MISSING)) {
		logErrorNL("Error opening records management db '%s'.",
		    rmDbPath.toUtf8().constData());
		return EXIT_FAILURE;
	}

465
	/* Load accounts from settings to account model. */
466 467 468
	{
		QSettings settings(Settings::settingsPath(),
		    QSettings::IniFormat);
469
		accountModelPtr->loadAccountsFromSettings(settings);
470 471 472 473
		/*
		 * No need to load counters here as some messages are likely
		 * to be deleted.
		 */
474 475
	}

Martin Straka's avatar
Martin Straka committed
476 477
	/*
	 * Open ZFO database, the second parameter means: true = zfo db will
478
	 * store on disk, false = only in memory
Martin Straka's avatar
Martin Straka committed
479
	 */
480 481
	if (!GlobInstcs::zfoDbPtr->openDb(
	        ZFO_DB_NAME, (GlobInstcs::setPtr->zfoDbSizeMBs > 0))) {
Martin Straka's avatar
Martin Straka committed
482 483 484
		qDebug() << "ERROR: zfo db not found!";
	}

485 486 487 488 489 490
	/* load UI (QML) */
	engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));

	/* OpenSSL support test */
	if (QSslSocket::supportsSsl()) {
		/* set last update text to status bar */
491 492
		if (!GlobInstcs::setPtr->lastUpdateStr().isEmpty() &&
		    GlobInstcs::setPtr->pinCode.isEmpty()) {
493
			emit isds.statusBarTextChanged(
Karel Slaný's avatar
Karel Slaný committed
494
			    QObject::tr("Last synchronisation: %1").
495
			    arg(GlobInstcs::setPtr->lastUpdateStr()), false, true);
496 497
		}
	} else {
498
		Dialogues::errorMessage(Dialogues::WARNING,
499
		    QObject::tr("Security problem"),
500 501
		    QObject::tr("OpenSSL support is required!"),
		    QObject::tr("The device does not support OpenSSL. "
502
		        "The application won't work correctly."));
503 504
	}

505
	/* Deletion of messages from db is disabled when equal to 0. */
506
	if (GlobInstcs::setPtr->msgLifeTimeInDays > 0) {
507
		messages.deleteExpiredMessagesFromDbs(
508
		    GlobInstcs::setPtr->msgLifeTimeInDays);
509 510
	}

511
	/* Deletion of files from db is disabled when equal to 0. */
512
	if (GlobInstcs::setPtr->fileLifeTimeInDays > 0) {
513
		files.deleteExpiredFilesFromDbs(
514
		    GlobInstcs::setPtr->fileLifeTimeInDays);
515 516
	}

517
	/* Inactivity locking is disabled when equal to 0. */
518
	if (GlobInstcs::setPtr->pinInactTimeoutInSecs > 0) {
519
		locker.setInactivityInterval(
520
		    GlobInstcs::setPtr->pinInactTimeoutInSecs);
521 522
	}

523
	/* Load counters. */
524
	Accounts::loadModelCounters(accountModelPtr);
525

526 527 528 529
	/*
	 * Show PIN screen if needed. Encoded PIN is checked because it hasn't
	 * been decoded yet.
	 */
530
	if (!GlobInstcs::setPtr->pinCode.isEmpty()) {
531 532
		emit locker.lockApp();
	}
533

534
	/*
535
	 * Open files passed via command line.
536 537
	 */
	if (!cmdLineFileNames.isEmpty()) {
538 539 540
		foreach (const QString &filePath, cmdLineFileNames) {
			interactionZfoFile.openZfoFile(filePath);
		}
541
	}
542
#if defined(Q_OS_ANDROID)
543
	IntentNotification intentNotification(interactionZfoFile);
544 545
	QObject::connect(&app, SIGNAL(applicationStateChanged(Qt::ApplicationState)),
	    &intentNotification, SLOT(scanIntentsForFiles(Qt::ApplicationState)));
546
#endif /* defined(Q_OS_ANDROID) */
547

548 549
	QmlInputDialogue::searchPersistentDialogues(&engine);

550 551 552
	/* Run app main event loop */
	int ret = app.exec();

553 554
	/* Wait until all threads finished. */
	logInfoNL("%s", "Waiting for pending worker threads.");
555 556
	GlobInstcs::workPoolPtr->wait();
	GlobInstcs::workPoolPtr->stop();
557 558
	logInfoNL("%s", "All worker threads finished");

559 560 561
	/* Close all OTP connections if exist */
	isds.closeAllOtpConnections();

562 563 564 565
	/*
	 * Store the configuration only when PIN has been recovered or is not
	 * used.
	 */
566 567
	if (!GlobInstcs::setPtr->_pinVal.isEmpty() ||
	    !GlobInstcs::setPtr->pinConfigured()) {
568 569 570 571
		/*
		 * The PIN was set/recovered or
		 * incomplete data to check/recover the PIN were supplied.
		 */
572
		GlobalSettingsQmlWrapper::saveAllSettings(accountModelPtr);
573
	}
574

575 576
	delete accountModelPtr;
	accountModelPtr = Q_NULLPTR;
577

578 579
	/* Destroy globally accessible objects. */
	{
580 581 582 583 584 585 586
		delete GlobInstcs::recMgmtDbPtr; GlobInstcs::recMgmtDbPtr = Q_NULLPTR;
		GlobInstcs::zfoDbPtr = Q_NULLPTR;
		GlobInstcs::fileDbsPtr = Q_NULLPTR;
		GlobInstcs::messageDbsPtr = Q_NULLPTR;
		GlobInstcs::accountDbPtr = Q_NULLPTR;

		delete GlobInstcs::setPtr; GlobInstcs::setPtr = Q_NULLPTR;
587

588 589
		delete GlobInstcs::workPoolPtr; GlobInstcs::workPoolPtr = Q_NULLPTR;
		delete GlobInstcs::msgProcEmitterPtr; GlobInstcs::msgProcEmitterPtr = Q_NULLPTR;
590 591
	}

592 593
	return ret;
}