2 * @file PswGen/Storage/module.cpp
3 * @brief Implementation of the iStorage interface
6 * Copyright (c) 2011-2012 Enar Vaikene
8 * This file is part of the eVaf C++ cross-platform application development framework.
10 * This file can be used under the terms of the GNU General Public License
11 * version 3.0 as published by the Free Software Foundation and appearing in
12 * the file LICENSE included in the packaging of this file. Please review the
13 * the following information to ensure the GNU General Public License version
14 * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
16 * Alternatively, this file may be used in accordance with the Commercial License
17 * Agreement provided with the Software.
22 #include <Common/Globals>
23 #include <Common/iLogger>
24 #include <Common/iRegistry>
25 #include <Common/iApp>
28 #include <QtSql/QtSql>
30 VER_EXPORT_VERSION_INFO()
33 using namespace eVaf::PswGen
;
34 using namespace eVaf::PswGen::Storage
;
36 //-------------------------------------------------------------------
42 setObjectName(QString("%1.%2").arg(VER_MODULE_NAME_STR
).arg(__FUNCTION__
));
44 mStorage
= new Internal::StorageImpl
;
46 EVAF_INFO("%s created", qPrintable(objectName()));
53 EVAF_INFO("%s destroyed", qPrintable(objectName()));
56 bool Module::init(QString
const & args
)
60 if (!mStorage
->init())
65 EVAF_INFO("%s initialized", qPrintable(objectName()));
76 EVAF_INFO("%s finalized", qPrintable(objectName()));
80 //-------------------------------------------------------------------
82 using namespace eVaf::PswGen::Storage::Internal
;
84 char const * const StorageImpl::DbConnectionName
= "PswGenDB";
86 char const * const StorageImpl::DbName
= "PswGen.sqlite";
88 StorageImpl::StorageImpl()
89 : QAbstractListModel()
91 setObjectName(QString("%1.iGenerator").arg(VER_MODULE_NAME_STR
));
93 EVAF_INFO("%s created", qPrintable(objectName()));
96 StorageImpl::~StorageImpl()
98 EVAF_INFO("%s destroyed", qPrintable(objectName()));
101 bool StorageImpl::init()
104 if (!QSqlDatabase::contains(DbConnectionName
)) {
105 // No database connection yet
106 mDb
= QSqlDatabase::addDatabase("QSQLITE", DbConnectionName
);
107 mDb
.setDatabaseName(Common::iApp::instance()->dataRootDir() + DbName
);
109 QSqlError err
= mDb
.lastError();
110 EVAF_ERROR("Failed to open database : %s", qPrintable(err
.text()));
115 // Database connection already exists
116 mDb
= QSqlDatabase::database(DbConnectionName
);
119 // Create tables if necessary
127 /// Register our interface
128 Common::iRegistry::instance()->registerInterface("iStorage", this);
130 EVAF_INFO("%s initialized", qPrintable(objectName()));
135 void StorageImpl::done()
139 EVAF_INFO("%s finalized", qPrintable(objectName()));
142 bool StorageImpl::save(QString
const & name
, QExplicitlySharedDataPointer
<Storage::Data
> data
)
144 EVAF_TEST_X(data
, "Data cannot be null");
145 EVAF_TEST_X(!name
.isEmpty(), "Name cannot be empty");
147 // Is it an update or a new data record?
148 if (mData
.constFind(name
) != mData
.constEnd()) {
150 if (data
->modified()) {
152 if (!q
.exec(QString("UPDATE data SET suffix = \'%1\', length = \'%2\', flags = \'%3\' WHERE name = \'%4\';")
153 .arg(data
->suffix()).arg(data
->length()).arg(data
->flags()).arg(name
))) {
154 QSqlError err
= mDb
.lastError();
155 EVAF_ERROR("Failed to update \'%s\' : %s", qPrintable(name
), qPrintable(err
.text()));
161 // Store to the database
163 if (!q
.exec(QString("INSERT INTO data (name, suffix, length, flags) VALUES (\'%1\', \'%2\', %3, %4);")
164 .arg(name
).arg(data
->suffix()).arg(data
->length())
165 .arg(int(data
->flags())))) {
166 QSqlError err
= mDb
.lastError();
167 EVAF_ERROR("Failed to insert \'%s\' : %s", qPrintable(name
), qPrintable(err
.text()));
171 // Store also into the local hash
173 mData
.insert(name
, data
);
183 QExplicitlySharedDataPointer
<Storage::Data
> StorageImpl::query(QString
const & name
) const
185 QMap
<QString
, QExplicitlySharedDataPointer
<Storage::Data
> >::const_iterator it
= mData
.constFind(name
);
186 if (it
!= mData
.constEnd())
189 return QExplicitlySharedDataPointer
<Storage::Data
>();
192 QVariant
StorageImpl::data(QModelIndex
const & index
, int role
) const
194 if (!index
.isValid() || index
.row() < 0 || index
.row() >= mData
.size() || index
.column() != 0)
197 if (role
== Qt::EditRole
|| role
== Qt::DisplayRole
)
198 return mData
.keys().at(index
.row());
203 bool StorageImpl::createTables()
206 if (!q
.exec("SELECT name FROM sqlite_master WHERE type=\'table\' AND name=\'data\';")) {
207 QSqlError err
= mDb
.lastError();
208 EVAF_ERROR("Failed to query database : %s", qPrintable(err
.text()));
212 if (q
.isActive() && q
.isSelect() && q
.first()) {
213 // Check if the table needs to be upgraded
214 return upgradeTables();
217 // Create the 'data' table
218 if (!q
.exec("CREATE TABLE data (name text primary key not null, suffix text, length integer, flags integer);")) {
219 QSqlError err
= mDb
.lastError();
220 EVAF_ERROR("Failed to create table \'data\' : %s", qPrintable(err
.text()));
227 bool StorageImpl::upgradeTables()
231 // Check if the 'suffix' column exists
232 if (q
.exec("SELECT suffix from data;")) {
236 // Add the 'suffix' columnt
237 if (!q
.exec("ALTER TABLE data ADD COLUMN suffix TEXT;")) {
238 QSqlError err
= mDb
.lastError();
239 EVAF_ERROR("Failed to upgrade table \'data\' : %s", qPrintable(err
.text()));
246 bool StorageImpl::loadData()
249 if (!q
.exec("SELECT name, suffix, length, flags FROM data;")) {
250 QSqlError err
= mDb
.lastError();
251 EVAF_ERROR("Failed to query database : %s", qPrintable(err
.text()));
257 QString name
= q
.value(0).toString();
258 QExplicitlySharedDataPointer
<Storage::Data
> data(
259 new Storage::Data(name
, q
.value(1).toString(), q
.value(2).toInt(), uint(q
.value(3).toInt())));
260 mData
.insert(name
, data
);