]> vaikene.ee Git - evaf/blob - src/apps/PswGen/Storage/module.cpp
b7676abf282f0d1323855a54919a676048619a43
[evaf] / src / apps / PswGen / Storage / module.cpp
1 /**
2 * @file PswGen/Storage/module.cpp
3 * @brief Implementation of the iStorage interface
4 * @author Enar Vaikene
5 *
6 * Copyright (c) 2011 Enar Vaikene
7 *
8 * This file is part of the eVaf C++ cross-platform application development framework.
9 *
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.
15 *
16 * Alternatively, this file may be used in accordance with the Commercial License
17 * Agreement provided with the Software.
18 */
19
20 #include "module.h"
21 #include "version.h"
22
23 #include <Common/Globals>
24 #include <Common/iLogger>
25 #include <Common/iRegistry>
26 #include <Common/iApp>
27
28 #include <QtCore>
29 #include <QtSql/QtSql>
30
31 VER_EXPORT_VERSION_INFO()
32 Q_EXPORT_PLUGIN2(VER_MODULE_NAME_STR, eVaf::PswGen::Storage::Module)
33
34 using namespace eVaf;
35 using namespace eVaf::PswGen;
36 using namespace eVaf::PswGen::Storage;
37
38 //-------------------------------------------------------------------
39
40 Module::Module()
41 : Plugins::iPlugin()
42 , mReady(false)
43 {
44 setObjectName(QString("%1.%2").arg(VER_MODULE_NAME_STR).arg(__FUNCTION__));
45
46 mStorage = new Internal::StorageImpl;
47
48 EVAF_INFO("%s created", qPrintable(objectName()));
49 }
50
51 Module::~Module()
52 {
53 delete mStorage;
54
55 EVAF_INFO("%s destroyed", qPrintable(objectName()));
56 }
57
58 bool Module::init(QString const & args)
59 {
60 Q_UNUSED(args);
61
62 if (!mStorage->init())
63 return false;
64
65 mReady = true;
66
67 EVAF_INFO("%s initialized", qPrintable(objectName()));
68
69 return true;
70 }
71
72 void Module::done()
73 {
74 mReady = false;
75
76 mStorage->done();
77
78 EVAF_INFO("%s finalized", qPrintable(objectName()));
79 }
80
81
82 //-------------------------------------------------------------------
83
84 using namespace eVaf::PswGen::Storage::Internal;
85
86 char const * const StorageImpl::DbConnectionName = "PswGenDB";
87
88 char const * const StorageImpl::DbName = "PswGen.sqlite";
89
90 StorageImpl::StorageImpl()
91 : QAbstractListModel()
92 {
93 setObjectName(QString("%1.iGenerator").arg(VER_MODULE_NAME_STR));
94
95 EVAF_INFO("%s created", qPrintable(objectName()));
96 }
97
98 StorageImpl::~StorageImpl()
99 {
100 EVAF_INFO("%s destroyed", qPrintable(objectName()));
101 }
102
103 bool StorageImpl::init()
104 {
105 // Open the database
106 if (!QSqlDatabase::contains(DbConnectionName)) {
107 // No database connection yet
108 mDb = QSqlDatabase::addDatabase("QSQLITE", DbConnectionName);
109 mDb.setDatabaseName(Common::iApp::instance()->dataRootDir() + DbName);
110 if (!mDb.open()) {
111 QSqlError err = mDb.lastError();
112 EVAF_ERROR("Failed to open database : %s", qPrintable(err.text()));
113 return false;
114 }
115 }
116 else {
117 // Database connection already exists
118 mDb = QSqlDatabase::database(DbConnectionName);
119 }
120
121 // Create tables if necessary
122 if (!createTables())
123 return false;
124
125 // Load data
126 if (!loadData())
127 return false;
128
129 /// Register our interface
130 Common::iRegistry::instance()->registerInterface("iStorage", this);
131
132 EVAF_INFO("%s initialized", qPrintable(objectName()));
133
134 return true;
135 }
136
137 void StorageImpl::done()
138 {
139 mData.clear();
140 EVAF_INFO("%s finalized", qPrintable(objectName()));
141 }
142
143 bool StorageImpl::save(QString const & name, QExplicitlySharedDataPointer<Storage::Data> data)
144 {
145 EVAF_TEST_X(data, "Data cannot be null");
146 EVAF_TEST_X(!name.isEmpty(), "Name cannot be empty");
147
148 // Is it an update or a new data record?
149 if (mData.constFind(name) != mData.constEnd()) {
150 // This is an update
151 if (data->modified()) {
152 QSqlQuery q(mDb);
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()));
157 return false;
158 }
159 }
160 }
161 else {
162 // Store to the database
163 QSqlQuery q(mDb);
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()));
169 return false;
170 }
171
172 // Store also into the local hash
173 mData.insert(name, data);
174
175 // Reset the model
176 reset();
177 }
178
179 data->reset();
180
181 return true;
182 }
183
184 QExplicitlySharedDataPointer<Storage::Data> StorageImpl::query(QString const & name) const
185 {
186 QMap<QString, QExplicitlySharedDataPointer<Storage::Data> >::const_iterator it = mData.constFind(name);
187 if (it != mData.constEnd())
188 return it.value();
189 else
190 return QExplicitlySharedDataPointer<Storage::Data>();
191 }
192
193 QVariant StorageImpl::data(QModelIndex const & index, int role) const
194 {
195 if (!index.isValid() || index.row() < 0 || index.row() >= mData.size() || index.column() != 0)
196 return QVariant();
197
198 if (role == Qt::EditRole || role == Qt::DisplayRole)
199 return mData.keys().at(index.row());
200
201 return QVariant();
202 }
203
204 bool StorageImpl::createTables()
205 {
206 QSqlQuery q(mDb);
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()));
210 return false;
211 }
212
213 if (q.isActive() && q.isSelect() && q.first())
214 return true; // We already have a table called 'data'
215
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()));
220 return false;
221 }
222
223 return true;
224 }
225
226 bool StorageImpl::loadData()
227 {
228 QSqlQuery q(mDb);
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()));
232 return false;
233 }
234
235 while (q.next()) {
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);
239 }
240
241 reset();
242
243 return true;
244 }