2 * @file PswGen/Storage/module.cpp
3 * @brief Implementation of the iStorage interface
6 * Copyright (c) 2011 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.
23 #include <Common/Globals>
24 #include <Common/iLogger>
25 #include <Common/iRegistry>
26 #include <Common/iEnv>
29 #include <QtSql/QtSql>
31 VER_EXPORT_VERSION_INFO()
32 Q_EXPORT_PLUGIN2(VER_MODULE_NAME_STR
, eVaf::PswGen::Storage::Module
)
35 using namespace eVaf::PswGen
;
36 using namespace eVaf::PswGen::Storage
;
38 //-------------------------------------------------------------------
44 setObjectName(QString("%1.%2").arg(VER_MODULE_NAME_STR
).arg(__FUNCTION__
));
46 mStorage
= new Internal::StorageImpl
;
48 EVAF_INFO("%s created", qPrintable(objectName()));
55 EVAF_INFO("%s destroyed", qPrintable(objectName()));
58 bool Module::init(QString
const & args
)
62 if (!mStorage
->init())
67 EVAF_INFO("%s initialized", qPrintable(objectName()));
78 EVAF_INFO("%s finalized", qPrintable(objectName()));
82 //-------------------------------------------------------------------
84 using namespace eVaf::PswGen::Storage::Internal
;
86 char const * const StorageImpl::DbConnectionName
= "PswGenDB";
88 char const * const StorageImpl::DbName
= "PswGen.sqlite";
90 StorageImpl::StorageImpl()
91 : QAbstractListModel()
93 setObjectName(QString("%1.iGenerator").arg(VER_MODULE_NAME_STR
));
95 EVAF_INFO("%s created", qPrintable(objectName()));
98 StorageImpl::~StorageImpl()
100 EVAF_INFO("%s destroyed", qPrintable(objectName()));
103 bool StorageImpl::init()
105 EVAF_INFO("%s initialized", qPrintable(objectName()));
108 if (!QSqlDatabase::contains(DbConnectionName
)) {
109 // No database connection yet
110 mDb
= QSqlDatabase::addDatabase("QSQLITE", DbConnectionName
);
111 mDb
.setDatabaseName(Common::iEnv::instance()->dataRootDir() + DbName
);
113 QSqlError err
= mDb
.lastError();
114 EVAF_ERROR("Failed to open database : %s", qPrintable(err
.text()));
119 // Database connection already exists
120 mDb
= QSqlDatabase::database(DbConnectionName
);
123 // Create tables if necessary
131 /// Register our interface
132 Common::iRegistry::instance()->registerInterface("iStorage", this);
137 void StorageImpl::done()
140 EVAF_INFO("%s finalized", qPrintable(objectName()));
143 bool StorageImpl::save(QString
const & name
, QExplicitlySharedDataPointer
<Storage::Data
> data
)
145 EVAF_TEST_X(data
, "Data cannot be null");
146 EVAF_TEST_X(!name
.isEmpty(), "Name cannot be empty");
148 // Is it an update or a new data record?
149 if (mData
.constFind(name
) != mData
.constEnd()) {
151 if (data
->modified()) {
153 if (!q
.exec(QString("UPDATE data SET length = \'%1\', flags = \'%2\' WHERE name = \'%3\';").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, length, flags) VALUES (\'%1\', %2, %3);").arg(name
).arg(data
->length()).arg(int(data
->flags())))) {
164 QSqlError err
= mDb
.lastError();
165 EVAF_ERROR("Failed to insert \'%s\' : %s", qPrintable(name
), qPrintable(err
.text()));
169 // Store also into the local hash
170 mData
.insert(name
, data
);
181 QExplicitlySharedDataPointer
<Storage::Data
> StorageImpl::query(QString
const & name
) const
183 QMap
<QString
, QExplicitlySharedDataPointer
<Storage::Data
> >::const_iterator it
= mData
.constFind(name
);
184 if (it
!= mData
.constEnd())
187 return QExplicitlySharedDataPointer
<Storage::Data
>();
190 QVariant
StorageImpl::data(QModelIndex
const & index
, int role
) const
192 if (!index
.isValid() || index
.row() < 0 || index
.row() >= mData
.size() || index
.column() != 0)
195 if (role
== Qt::EditRole
|| role
== Qt::DisplayRole
)
196 return mData
.keys().at(index
.row());
201 bool StorageImpl::createTables()
204 if (!q
.exec("SELECT name FROM sqlite_master WHERE type=\'table\' AND name=\'data\';")) {
205 QSqlError err
= mDb
.lastError();
206 EVAF_ERROR("Failed to query database : %s", qPrintable(err
.text()));
210 if (q
.isActive() && q
.isSelect() && q
.first())
211 return true; // We already have a table called 'data'
213 // Create the 'data' table
214 if (!q
.exec("CREATE TABLE data (name text primary key not null, length integer, flags integer);")) {
215 QSqlError err
= mDb
.lastError();
216 EVAF_ERROR("Failed to create table \'data\' : %s", qPrintable(err
.text()));
223 bool StorageImpl::loadData()
226 if (!q
.exec("SELECT name, length, flags FROM data;")) {
227 QSqlError err
= mDb
.lastError();
228 EVAF_ERROR("Failed to query database : %s", qPrintable(err
.text()));
233 QString name
= q
.value(0).toString();
234 QExplicitlySharedDataPointer
<Storage::Data
> data(new Storage::Data(q
.value(1).toInt(), uint(q
.value(2).toInt())));
235 mData
.insert(name
, data
);