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/iApp>
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()
106 if (!QSqlDatabase::contains(DbConnectionName
)) {
107 // No database connection yet
108 mDb
= QSqlDatabase::addDatabase("QSQLITE", DbConnectionName
);
109 mDb
.setDatabaseName(Common::iApp::instance()->dataRootDir() + DbName
);
111 QSqlError err
= mDb
.lastError();
112 EVAF_ERROR("Failed to open database : %s", qPrintable(err
.text()));
117 // Database connection already exists
118 mDb
= QSqlDatabase::database(DbConnectionName
);
121 // Create tables if necessary
129 /// Register our interface
130 Common::iRegistry::instance()->registerInterface("iStorage", this);
132 EVAF_INFO("%s initialized", qPrintable(objectName()));
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\';")
154 .arg(data
->length()).arg(data
->flags()).arg(name
))) {
155 QSqlError err
= mDb
.lastError();
156 EVAF_ERROR("Failed to update \'%s\' : %s", qPrintable(name
), qPrintable(err
.text()));
162 // Store to the database
164 if (!q
.exec(QString("INSERT INTO data (name, length, flags) VALUES (\'%1\', %2, %3);")
165 .arg(name
).arg(data
->length())
166 .arg(int(data
->flags())))) {
167 QSqlError err
= mDb
.lastError();
168 EVAF_ERROR("Failed to insert \'%s\' : %s", qPrintable(name
), qPrintable(err
.text()));
172 // Store also into the local hash
173 mData
.insert(name
, data
);
184 QExplicitlySharedDataPointer
<Storage::Data
> StorageImpl::query(QString
const & name
) const
186 QMap
<QString
, QExplicitlySharedDataPointer
<Storage::Data
> >::const_iterator it
= mData
.constFind(name
);
187 if (it
!= mData
.constEnd())
190 return QExplicitlySharedDataPointer
<Storage::Data
>();
193 QVariant
StorageImpl::data(QModelIndex
const & index
, int role
) const
195 if (!index
.isValid() || index
.row() < 0 || index
.row() >= mData
.size() || index
.column() != 0)
198 if (role
== Qt::EditRole
|| role
== Qt::DisplayRole
)
199 return mData
.keys().at(index
.row());
204 bool StorageImpl::createTables()
207 if (!q
.exec("SELECT name FROM sqlite_master WHERE type=\'table\' AND name=\'data\';")) {
208 QSqlError err
= mDb
.lastError();
209 EVAF_ERROR("Failed to query database : %s", qPrintable(err
.text()));
213 if (q
.isActive() && q
.isSelect() && q
.first())
214 return true; // We already have a table called 'data'
216 // Create the 'data' table
217 if (!q
.exec("CREATE TABLE data (name text primary key not null, length integer, flags integer);")) {
218 QSqlError err
= mDb
.lastError();
219 EVAF_ERROR("Failed to create table \'data\' : %s", qPrintable(err
.text()));
226 bool StorageImpl::loadData()
229 if (!q
.exec("SELECT name, length, flags FROM data;")) {
230 QSqlError err
= mDb
.lastError();
231 EVAF_ERROR("Failed to query database : %s", qPrintable(err
.text()));
236 QString name
= q
.value(0).toString();
237 QExplicitlySharedDataPointer
<Storage::Data
> data(new Storage::Data(name
, q
.value(1).toInt(), uint(q
.value(2).toInt())));
238 mData
.insert(name
, data
);