1 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html lang=
"et" xmlns=
"http://www.w3.org/1999/xhtml" xml:
lang=
"et">
5 <meta http-equiv=
"CONTENT-TYPE" content=
"text/html; charset=utf-8" />
6 <title>eVaf Tutorial -
07 - Storage Module
</title>
7 <meta name=
"Author" content=
"Enar Väikene" />
8 <meta name=
"description" content=
"eVaf Tutorial" />
9 <meta name=
"keywords" content=
"evaf c++ application development framework tutorial password generator" />
10 <link rel=
"StyleSheet" href=
"evaf.css" type=
"text/css" media=
"all" />
11 <link rel=
"StyleSheet" href=
"highlight.css" type=
"text/css" media=
"all" />
16 <p>Next:
<a href=
"pswgen08.html">08 - Building Storage Module
</a>, Previous:
<a href=
"pswgen06.html">06 - Storage Module
</a></p>
18 <h1>eVaf Tutorial
</h1>
20 <h2>07 - Storage Module
</h2>
22 <p>Create the
<tt>module.cpp
</tt> file in the
<tt>src/apps/PswGen/Storage
</tt> directory:
</tt>
24 <pre class=
"hl"><span class=
"hl com">/**
</span>
25 <span class=
"hl com"> *
@file PswGen/Storage/module.cpp
</span>
26 <span class=
"hl com"> */
</span>
28 <span class=
"hl ppc">#include
</span> <span class=
"hl pps">"module.h
"</span><span class=
"hl ppc"></span>
29 <span class=
"hl ppc">#include
<QtCore
></span></pre>
31 <p>Copy version information files from the
<tt>Generator
<tt> module:
</p>
33 <pre>evaf/src/apps/PswGen/Storage $
<code>cp ../Generator/version.{h,rc} .
</code></pre>
35 <p>Modify the
<tt>version.h
</tt> file:
</p>
37 <pre class=
"hl"><span class=
"hl com">/**
</span>
38 <span class=
"hl com"> *
@file PswGen/Storage/version.h
</span>
39 <span class=
"hl com"> */
</span>
41 <span class=
"hl ppc">#ifndef __PSWGEN_STORAGE_VERSION_H
</span>
42 <span class=
"hl ppc">#define __PSWGEN_STORAGE_VERSION_H
</span>
44 <span class=
"hl ppc">#include
<version_rc.h
></span>
46 <span class=
"hl com">/**
</span>
47 <span class=
"hl com"> * Module/library version number in the form major,minor,release,build
</span>
48 <span class=
"hl com"> */
</span>
49 <span class=
"hl ppc">#define VER_FILE_VERSION
0,
1,
1,
1</span>
51 <span class=
"hl com">/**
</span>
52 <span class=
"hl com"> * Module/library version number in the string format (shall end with \
0)
</span>
53 <span class=
"hl com"> */
</span>
54 <span class=
"hl ppc">#define VER_FILE_VERSION_STR
</span> <span class=
"hl pps">"0.1.1.1\
0"</span><span class=
"hl ppc"></span>
56 <span class=
"hl com">/**
</span>
57 <span class=
"hl com"> * Module/library name (shall end with \
0)
</span>
58 <span class=
"hl com"> */
</span>
59 <span class=
"hl ppc">#define VER_MODULE_NAME_STR
</span> <span class=
"hl pps">"PswStorage\
0"</span><span class=
"hl ppc"></span>
61 <span class=
"hl com">/**
</span>
62 <span class=
"hl com"> * Module type (see version_rc.h for all the types)
</span>
63 <span class=
"hl com"> */
</span>
64 <span class=
"hl ppc">#define VER_MODULE_TYPE MT_GENERIC
</span>
66 <span class=
"hl com">/**
</span>
67 <span class=
"hl com"> * Module type in the string format (see version_rc for all the types)
</span>
68 <span class=
"hl com"> */
</span>
69 <span class=
"hl ppc">#define VER_MODULE_TYPE_STR MT_GENERIC
</span>
71 <span class=
"hl com">/**
</span>
72 <span class=
"hl com"> * Original file name for windows (shall end with \
0)
</span>
73 <span class=
"hl com"> */
</span>
74 <span class=
"hl ppc">#define VER_ORIGINAL_FILE_NAME_STR
</span> <span class=
"hl pps">"PswStorage.dll\
0"</span><span class=
"hl ppc"></span>
76 <span class=
"hl com">/**
</span>
77 <span class=
"hl com"> * Description of the module/library (shall end with \
0)
</span>
78 <span class=
"hl com"> */
</span>
79 <span class=
"hl ppc">#define VER_FILE_DESCRIPTION_STR
</span> <span class=
"hl pps">"Module that stores data for generating strong passwords.\
0"</span><span class=
"hl ppc"></span>
81 <span class=
"hl ppc">#endif
</span> <span class=
"hl slc">// version.h
</span><span class=
"hl ppc"></span></pre>
83 <p>Include the
<tt>version.h
</tt> header file in
<tt>module.cpp
</tt> and export version information:
</p>
86 <span class=
"hl ppc">#include
</span> <span class=
"hl pps">"version.h
"</span><span class=
"hl ppc"></span>
88 <span class=
"hl kwd">VER_EXPORT_VERSION_INFO
</span><span class=
"hl opt">()
</span></pre>
90 <p>Make it a proper Qt plugin by using the
<tt>Q_EXPORT_PLUGIN2()
</tt> macro:
</p>
92 <pre class=
"hl"><span class=
"hl kwd">Q_EXPORT_PLUGIN2
</span><span class=
"hl opt">(
</span>VER_MODULE_NAME_STR
<span class=
"hl opt">,
</span> eVaf
<span class=
"hl opt">::
</span>PswGen
<span class=
"hl opt">::
</span>Storage
<span class=
"hl opt">::
</span>Module
<span class=
"hl opt">)
</span></pre>
94 <p>The
<tt>Module
</tt> class creates the internal
<tt>StorageImpl
</tt> object in the constructor, but initializes it in the
95 <tt>init()
</tt> method. This way we can return errors from the module if initialization fails. Similarly, we finalize the
96 internal
<tt>StorageImpl
</tt> object in the
<tt>done()
</tt> method and delete in the destructor.
</p>
98 <p>The module is ready when the internal
<tt>StorageImpl
</tt> object is initalized and we set the
<tt>mReady
</tt> flag to
99 <tt>true
</tt> when the initialization is done and back to
<tt>false
</tt> in the
<tt>done()
</tt> method.
</p>
101 <p>The rest of the code sets the name of the object and outputs info messages.
</p>
103 <pre class=
"hl">Module
<span class=
"hl opt">::
</span><span class=
"hl kwd">Module
</span><span class=
"hl opt">()
</span>
104 <span class=
"hl opt">:
</span> Plugins
<span class=
"hl opt">::
</span><span class=
"hl kwd">iPlugin
</span><span class=
"hl opt">()
</span>
105 <span class=
"hl opt">,
</span> <span class=
"hl kwd">mReady
</span><span class=
"hl opt">(
</span><span class=
"hl kwa">false
</span><span class=
"hl opt">)
</span>
106 <span class=
"hl opt">{
</span>
107 <span class=
"hl kwd">setObjectName
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">QString
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%
1.%
2"</span><span class=
"hl opt">).
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>VER_MODULE_NAME_STR
<span class=
"hl opt">).
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>__FUNCTION__
<span class=
"hl opt">));
</span>
109 mStorage
<span class=
"hl opt">=
</span> <span class=
"hl kwa">new
</span> Internal
<span class=
"hl opt">::
</span>StorageImpl
<span class=
"hl opt">;
</span>
111 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s created
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
112 <span class=
"hl opt">}
</span>
114 Module
<span class=
"hl opt">::~
</span><span class=
"hl kwd">Module
</span><span class=
"hl opt">()
</span>
115 <span class=
"hl opt">{
</span>
116 <span class=
"hl kwa">delete
</span> mStorage
<span class=
"hl opt">;
</span>
118 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s destroyed
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
119 <span class=
"hl opt">}
</span>
121 <span class=
"hl kwb">bool
</span> Module
<span class=
"hl opt">::
</span><span class=
"hl kwd">init
</span><span class=
"hl opt">(
</span>QString
<span class=
"hl kwb">const
</span> <span class=
"hl opt">&</span> args
<span class=
"hl opt">)
</span>
122 <span class=
"hl opt">{
</span>
123 <span class=
"hl kwd">Q_UNUSED
</span><span class=
"hl opt">(
</span>args
<span class=
"hl opt">);
</span>
125 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>mStorage
<span class=
"hl opt">-
></span><span class=
"hl kwd">init
</span><span class=
"hl opt">())
</span>
126 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
128 mReady
<span class=
"hl opt">=
</span> <span class=
"hl kwa">true
</span><span class=
"hl opt">;
</span>
130 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s initialized
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
132 <span class=
"hl kwa">return true
</span><span class=
"hl opt">;
</span>
133 <span class=
"hl opt">}
</span>
135 <span class=
"hl kwb">void
</span> Module
<span class=
"hl opt">::
</span><span class=
"hl kwd">done
</span><span class=
"hl opt">()
</span>
136 <span class=
"hl opt">{
</span>
137 mReady
<span class=
"hl opt">=
</span> <span class=
"hl kwa">false
</span><span class=
"hl opt">;
</span>
139 mStorage
<span class=
"hl opt">-
></span><span class=
"hl kwd">done
</span><span class=
"hl opt">();
</span>
141 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s finalized
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
142 <span class=
"hl opt">}
</span></pre>
144 <p>The
<tt>StorageImpl
</tt> class does very little in the constructor and in the destructor:
</p>
146 <pre class=
"hl">StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">StorageImpl
</span><span class=
"hl opt">()
</span>
147 <span class=
"hl opt">:
</span> <span class=
"hl kwd">QAbstractListModel
</span><span class=
"hl opt">()
</span>
148 <span class=
"hl opt">{
</span>
149 <span class=
"hl kwd">setObjectName
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">QString
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%
1.iGenerator
"</span><span class=
"hl opt">).
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>VER_MODULE_NAME_STR
<span class=
"hl opt">));
</span>
151 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s created
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
152 <span class=
"hl opt">}
</span>
154 StorageImpl
<span class=
"hl opt">::~
</span><span class=
"hl kwd">StorageImpl
</span><span class=
"hl opt">()
</span>
155 <span class=
"hl opt">{
</span>
156 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s destroyed
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
157 <span class=
"hl opt">}
</span></pre>
159 <p>Initialization of the
<tt>StorageImpl
</tt> class happens in the
<tt>init()
</tt> method, where we open the database connection,
160 create tables if necessary and load data from the database. We also register the
<tt>iStorage
</tt> interface in the global
161 registry of interfaces.
</p>
163 <p>We use the
<tt>Common::iApp
</tt> interface to find the data root directory where the SQLITE database file is going to be
166 <pre class=
"hl"><span class=
"hl kwb">bool
</span> StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">init
</span><span class=
"hl opt">()
</span>
167 <span class=
"hl opt">{
</span>
168 <span class=
"hl slc">// Open the database
</span>
169 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>QSqlDatabase
<span class=
"hl opt">::
</span><span class=
"hl kwd">contains
</span><span class=
"hl opt">(
</span>DbConnectionName
<span class=
"hl opt">)) {
</span>
170 <span class=
"hl slc">// No database connection yet
</span>
171 mDb
<span class=
"hl opt">=
</span> QSqlDatabase
<span class=
"hl opt">::
</span><span class=
"hl kwd">addDatabase
</span><span class=
"hl opt">(
</span><span class=
"hl str">"QSQLITE
"</span><span class=
"hl opt">,
</span> DbConnectionName
<span class=
"hl opt">);
</span>
172 mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">setDatabaseName
</span><span class=
"hl opt">(
</span>Common
<span class=
"hl opt">::
</span>iApp
<span class=
"hl opt">::
</span><span class=
"hl kwd">instance
</span><span class=
"hl opt">()-
></span><span class=
"hl kwd">dataRootDir
</span><span class=
"hl opt">() +
</span> DbName
<span class=
"hl opt">);
</span>
173 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">open
</span><span class=
"hl opt">()) {
</span>
174 QSqlError err
<span class=
"hl opt">=
</span> mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">lastError
</span><span class=
"hl opt">();
</span>
175 <span class=
"hl kwd">EVAF_ERROR
</span><span class=
"hl opt">(
</span><span class=
"hl str">"Failed to open database : %s
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>err
<span class=
"hl opt">.
</span><span class=
"hl kwd">text
</span><span class=
"hl opt">()));
</span>
176 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
177 <span class=
"hl opt">}
</span>
178 <span class=
"hl opt">}
</span>
179 <span class=
"hl kwa">else
</span> <span class=
"hl opt">{
</span>
180 <span class=
"hl slc">// Database connection already exists
</span>
181 mDb
<span class=
"hl opt">=
</span> QSqlDatabase
<span class=
"hl opt">::
</span><span class=
"hl kwd">database
</span><span class=
"hl opt">(
</span>DbConnectionName
<span class=
"hl opt">);
</span>
182 <span class=
"hl opt">}
</span>
184 <span class=
"hl slc">// Create tables if necessary
</span>
185 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span><span class=
"hl kwd">createTables
</span><span class=
"hl opt">())
</span>
186 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
188 <span class=
"hl slc">// Load data
</span>
189 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span><span class=
"hl kwd">loadData
</span><span class=
"hl opt">())
</span>
190 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
192 <span class=
"hl slc">/// Register our interface
</span>
193 Common
<span class=
"hl opt">::
</span>iRegistry
<span class=
"hl opt">::
</span><span class=
"hl kwd">instance
</span><span class=
"hl opt">()-
></span><span class=
"hl kwd">registerInterface
</span><span class=
"hl opt">(
</span><span class=
"hl str">"iStorage
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwa">this
</span><span class=
"hl opt">);
</span>
195 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s initialized
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
197 <span class=
"hl kwa">return true
</span><span class=
"hl opt">;
</span>
198 <span class=
"hl opt">}
</span></pre>
200 <p>The finalization of the
<tt>StorageImpl
</tt> class happens in the
<tt>done()
</tt> method, where we only need to clear the list
201 of shared data objects:
</p>
203 <pre class=
"hl"><span class=
"hl kwb">void
</span> StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">done
</span><span class=
"hl opt">()
</span>
204 <span class=
"hl opt">{
</span>
205 mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">clear
</span><span class=
"hl opt">();
</span>
206 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s finalized
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
207 <span class=
"hl opt">}
</span></pre>
209 <p>The
<tt>StorageImpl::save()
</tt> method verifies that the shared data object is valid and the name not empty. Then it either
210 adds a new data record to the database or updates an existing one.
</p>
212 <pre class=
"hl"><span class=
"hl kwb">bool
</span> StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">save
</span><span class=
"hl opt">(
</span>QString
<span class=
"hl kwb">const
</span> <span class=
"hl opt">&</span> name
<span class=
"hl opt">,
</span> QExplicitlySharedDataPointer
<span class=
"hl opt"><</span>Storage
<span class=
"hl opt">::
</span>Data
<span class=
"hl opt">></span> data
<span class=
"hl opt">)
</span>
213 <span class=
"hl opt">{
</span>
214 <span class=
"hl kwd">EVAF_TEST_X
</span><span class=
"hl opt">(
</span>data
<span class=
"hl opt">,
</span> <span class=
"hl str">"Data cannot be null
"</span><span class=
"hl opt">);
</span>
215 <span class=
"hl kwd">EVAF_TEST_X
</span><span class=
"hl opt">(!
</span>name
<span class=
"hl opt">.
</span><span class=
"hl kwd">isEmpty
</span><span class=
"hl opt">(),
</span> <span class=
"hl str">"Name cannot be empty
"</span><span class=
"hl opt">);
</span>
217 <span class=
"hl slc">// Is it an update or a new data record?
</span>
218 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(
</span>mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">constFind
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">) !=
</span> mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">constEnd
</span><span class=
"hl opt">()) {
</span>
219 <span class=
"hl slc">// This is an update
</span>
220 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(
</span>data
<span class=
"hl opt">-
></span><span class=
"hl kwd">modified
</span><span class=
"hl opt">()) {
</span>
221 QSqlQuery
<span class=
"hl kwd">q
</span><span class=
"hl opt">(
</span>mDb
<span class=
"hl opt">);
</span>
222 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">exec
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">QString
</span><span class=
"hl opt">(
</span><span class=
"hl str">"UPDATE data SET length =
</span> <span class=
"hl esc">\'
</span><span class=
"hl str">%
1</span><span class=
"hl esc">\'
</span><span class=
"hl str">, flags =
</span> <span class=
"hl esc">\'
</span><span class=
"hl str">%
2</span><span class=
"hl esc">\'
</span> <span class=
"hl str">WHERE name =
</span> <span class=
"hl esc">\'
</span><span class=
"hl str">%
3</span><span class=
"hl esc">\'
</span><span class=
"hl str">;
"</span><span class=
"hl opt">)
</span>
223 <span class=
"hl opt">.
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>data
<span class=
"hl opt">-
></span><span class=
"hl kwd">length
</span><span class=
"hl opt">()).
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>data
<span class=
"hl opt">-
></span><span class=
"hl kwd">flags
</span><span class=
"hl opt">()).
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">))) {
</span>
224 QSqlError err
<span class=
"hl opt">=
</span> mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">lastError
</span><span class=
"hl opt">();
</span>
225 <span class=
"hl kwd">EVAF_ERROR
</span><span class=
"hl opt">(
</span><span class=
"hl str">"Failed to update
</span> <span class=
"hl esc">\'
</span><span class=
"hl str">%s
</span><span class=
"hl esc">\'
</span> <span class=
"hl str">: %s
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">),
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>err
<span class=
"hl opt">.
</span><span class=
"hl kwd">text
</span><span class=
"hl opt">()));
</span>
226 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
227 <span class=
"hl opt">}
</span>
228 <span class=
"hl opt">}
</span>
229 <span class=
"hl opt">}
</span>
230 <span class=
"hl kwa">else
</span> <span class=
"hl opt">{
</span>
231 <span class=
"hl slc">// Store to the database
</span>
232 QSqlQuery
<span class=
"hl kwd">q
</span><span class=
"hl opt">(
</span>mDb
<span class=
"hl opt">);
</span>
233 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">exec
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">QString
</span><span class=
"hl opt">(
</span><span class=
"hl str">"INSERT INTO data (name, length, flags) VALUES (
</span><span class=
"hl esc">\'
</span><span class=
"hl str">%
1</span><span class=
"hl esc">\'
</span><span class=
"hl str">, %
2, %
3);
"</span><span class=
"hl opt">)
</span>
234 <span class=
"hl opt">.
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">).
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>data
<span class=
"hl opt">-
></span><span class=
"hl kwd">length
</span><span class=
"hl opt">())
</span>
235 <span class=
"hl opt">.
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span><span class=
"hl kwb">int
</span><span class=
"hl opt">(
</span>data
<span class=
"hl opt">-
></span><span class=
"hl kwd">flags
</span><span class=
"hl opt">())))) {
</span>
236 QSqlError err
<span class=
"hl opt">=
</span> mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">lastError
</span><span class=
"hl opt">();
</span>
237 <span class=
"hl kwd">EVAF_ERROR
</span><span class=
"hl opt">(
</span><span class=
"hl str">"Failed to insert
</span> <span class=
"hl esc">\'
</span><span class=
"hl str">%s
</span><span class=
"hl esc">\'
</span> <span class=
"hl str">: %s
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">),
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>err
<span class=
"hl opt">.
</span><span class=
"hl kwd">text
</span><span class=
"hl opt">()));
</span>
238 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
239 <span class=
"hl opt">}
</span>
241 <span class=
"hl slc">// Store also into the local hash
</span>
242 mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">insert
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">,
</span> data
<span class=
"hl opt">);
</span>
244 <span class=
"hl slc">// Reset the model
</span>
245 <span class=
"hl kwd">reset
</span><span class=
"hl opt">();
</span>
246 <span class=
"hl opt">}
</span>
248 data
<span class=
"hl opt">-
></span><span class=
"hl kwd">reset
</span><span class=
"hl opt">();
</span>
250 <span class=
"hl kwa">return true
</span><span class=
"hl opt">;
</span>
251 <span class=
"hl opt">}
</span></pre>
253 <p>Calling the
<tt>reset()
</tt> method resets the
<tt>QAbstractItemModel
</tt> data model and assures that the associated widget
254 updates the
<tt>QCompleter
</tt> with a fresh list of auto completion words. Resetting the data model in this case is fine as
255 long as the data model is simple and the list short. The proper way would be finding out the actual insertion point and using
256 <tt>beginInsertRows()
</tt> and
<tt>endInsertRows()
</tt> methods.
</p>
258 <p>Querying data is much simpler thanks to the internal
<tt>QMap
</tt> container:
</p>
260 <pre class=
"hl">QExplicitlySharedDataPointer
<span class=
"hl opt"><</span>Storage
<span class=
"hl opt">::
</span>Data
<span class=
"hl opt">></span> StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">query
</span><span class=
"hl opt">(
</span>QString
<span class=
"hl kwb">const
</span> <span class=
"hl opt">&</span> name
<span class=
"hl opt">)
</span> <span class=
"hl kwb">const
</span>
261 <span class=
"hl opt">{
</span>
262 QMap
<span class=
"hl opt"><</span>QString
<span class=
"hl opt">,
</span> QExplicitlySharedDataPointer
<span class=
"hl opt"><</span>Storage
<span class=
"hl opt">::
</span>Data
<span class=
"hl opt">> >::
</span>const_iterator it
<span class=
"hl opt">=
</span> mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">constFind
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">);
</span>
263 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(
</span>it
<span class=
"hl opt">!=
</span> mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">constEnd
</span><span class=
"hl opt">())
</span>
264 <span class=
"hl kwa">return
</span> it
<span class=
"hl opt">.
</span><span class=
"hl kwd">value
</span><span class=
"hl opt">();
</span>
265 <span class=
"hl kwa">else
</span>
266 <span class=
"hl kwa">return
</span> QExplicitlySharedDataPointer
<span class=
"hl opt"><</span>Storage
<span class=
"hl opt">::
</span>Data
<span class=
"hl opt">>();
</span>
267 <span class=
"hl opt">}
</span></pre>
269 <p>We return an empty
<tt>QExplicitlySharedDataPointer
</tt> object if no data objects with the given name exists.
</p>
271 <p>The
<tt>data()
</tt> method returns names of data objects for the
<tt>QCompleter
</tt> auto completion list of words:
</p>
273 <pre class=
"hl">QVariant StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">data
</span><span class=
"hl opt">(
</span>QModelIndex
<span class=
"hl kwb">const
</span> <span class=
"hl opt">&</span> index
<span class=
"hl opt">,
</span> <span class=
"hl kwb">int
</span> role
<span class=
"hl opt">)
</span> <span class=
"hl kwb">const
</span>
274 <span class=
"hl opt">{
</span>
275 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>index
<span class=
"hl opt">.
</span><span class=
"hl kwd">isValid
</span><span class=
"hl opt">() ||
</span> index
<span class=
"hl opt">.
</span><span class=
"hl kwd">row
</span><span class=
"hl opt">()
<</span> <span class=
"hl num">0</span> <span class=
"hl opt">||
</span> index
<span class=
"hl opt">.
</span><span class=
"hl kwd">row
</span><span class=
"hl opt">()
>=
</span> mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">size
</span><span class=
"hl opt">() ||
</span> index
<span class=
"hl opt">.
</span><span class=
"hl kwd">column
</span><span class=
"hl opt">() !=
</span> <span class=
"hl num">0</span><span class=
"hl opt">)
</span>
276 <span class=
"hl kwa">return
</span> <span class=
"hl kwd">QVariant
</span><span class=
"hl opt">();
</span>
278 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(
</span>role
<span class=
"hl opt">==
</span> Qt
<span class=
"hl opt">::
</span>EditRole
<span class=
"hl opt">||
</span> role
<span class=
"hl opt">==
</span> Qt
<span class=
"hl opt">::
</span>DisplayRole
<span class=
"hl opt">)
</span>
279 <span class=
"hl kwa">return
</span> mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">keys
</span><span class=
"hl opt">().
</span><span class=
"hl kwd">at
</span><span class=
"hl opt">(
</span>index
<span class=
"hl opt">.
</span><span class=
"hl kwd">row
</span><span class=
"hl opt">());
</span>
281 <span class=
"hl kwa">return
</span> <span class=
"hl kwd">QVariant
</span><span class=
"hl opt">();
</span>
282 <span class=
"hl opt">}
</span></pre>
284 <p>The
<tt>createTabled()
</tt> method creates the
<tt>data
</tt> table if it does not exist. This function could be improved to
285 alter the
<tt>data
</tt> table if it exists, but is from an older version. Right now we assume that if the table exists, it
286 is good for our application:
</p>
288 <pre class=
"hl"><span class=
"hl kwb">bool
</span> StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">createTables
</span><span class=
"hl opt">()
</span>
289 <span class=
"hl opt">{
</span>
290 QSqlQuery
<span class=
"hl kwd">q
</span><span class=
"hl opt">(
</span>mDb
<span class=
"hl opt">);
</span>
291 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">exec
</span><span class=
"hl opt">(
</span><span class=
"hl str">"SELECT name FROM sqlite_master WHERE type=
</span><span class=
"hl esc">\'
</span><span class=
"hl str">table
</span><span class=
"hl esc">\'
</span> <span class=
"hl str">AND name=
</span><span class=
"hl esc">\'
</span><span class=
"hl str">data
</span><span class=
"hl esc">\'
</span><span class=
"hl str">;
"</span><span class=
"hl opt">)) {
</span>
292 QSqlError err
<span class=
"hl opt">=
</span> mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">lastError
</span><span class=
"hl opt">();
</span>
293 <span class=
"hl kwd">EVAF_ERROR
</span><span class=
"hl opt">(
</span><span class=
"hl str">"Failed to query database : %s
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>err
<span class=
"hl opt">.
</span><span class=
"hl kwd">text
</span><span class=
"hl opt">()));
</span>
294 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
295 <span class=
"hl opt">}
</span>
297 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">isActive
</span><span class=
"hl opt">()
&&</span> q
<span class=
"hl opt">.
</span><span class=
"hl kwd">isSelect
</span><span class=
"hl opt">()
&&</span> q
<span class=
"hl opt">.
</span><span class=
"hl kwd">first
</span><span class=
"hl opt">())
</span>
298 <span class=
"hl kwa">return true
</span><span class=
"hl opt">;
</span> <span class=
"hl slc">// We already have a table called 'data'
</span>
300 <span class=
"hl slc">// Create the 'data' table
</span>
301 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">exec
</span><span class=
"hl opt">(
</span><span class=
"hl str">"CREATE TABLE data (name text primary key not null, length integer, flags integer);
"</span><span class=
"hl opt">)) {
</span>
302 QSqlError err
<span class=
"hl opt">=
</span> mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">lastError
</span><span class=
"hl opt">();
</span>
303 <span class=
"hl kwd">EVAF_ERROR
</span><span class=
"hl opt">(
</span><span class=
"hl str">"Failed to create table
</span> <span class=
"hl esc">\'
</span><span class=
"hl str">data
</span><span class=
"hl esc">\'
</span> <span class=
"hl str">: %s
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>err
<span class=
"hl opt">.
</span><span class=
"hl kwd">text
</span><span class=
"hl opt">()));
</span>
304 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
305 <span class=
"hl opt">}
</span>
307 <span class=
"hl kwa">return true
</span><span class=
"hl opt">;
</span>
308 <span class=
"hl opt">}
</span></pre>
310 <p>Finally, the
<tt>loadData()
</tt> method loads all the data records from the database to the memory:
</p>
312 <pre class=
"hl"><span class=
"hl kwb">bool
</span> StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">loadData
</span><span class=
"hl opt">()
</span>
313 <span class=
"hl opt">{
</span>
314 QSqlQuery
<span class=
"hl kwd">q
</span><span class=
"hl opt">(
</span>mDb
<span class=
"hl opt">);
</span>
315 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">exec
</span><span class=
"hl opt">(
</span><span class=
"hl str">"SELECT name, length, flags FROM data;
"</span><span class=
"hl opt">)) {
</span>
316 QSqlError err
<span class=
"hl opt">=
</span> mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">lastError
</span><span class=
"hl opt">();
</span>
317 <span class=
"hl kwd">EVAF_ERROR
</span><span class=
"hl opt">(
</span><span class=
"hl str">"Failed to query database : %s
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>err
<span class=
"hl opt">.
</span><span class=
"hl kwd">text
</span><span class=
"hl opt">()));
</span>
318 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
319 <span class=
"hl opt">}
</span>
321 <span class=
"hl kwa">while
</span> <span class=
"hl opt">(
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">next
</span><span class=
"hl opt">()) {
</span>
322 QString name
<span class=
"hl opt">=
</span> q
<span class=
"hl opt">.
</span><span class=
"hl kwd">value
</span><span class=
"hl opt">(
</span><span class=
"hl num">0</span><span class=
"hl opt">).
</span><span class=
"hl kwd">toString
</span><span class=
"hl opt">();
</span>
323 QExplicitlySharedDataPointer
<span class=
"hl opt"><</span>Storage
<span class=
"hl opt">::
</span>Data
<span class=
"hl opt">></span> <span class=
"hl kwd">data
</span><span class=
"hl opt">(
</span><span class=
"hl kwa">new
</span> Storage
<span class=
"hl opt">::
</span><span class=
"hl kwd">Data
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">,
</span> q
<span class=
"hl opt">.
</span><span class=
"hl kwd">value
</span><span class=
"hl opt">(
</span><span class=
"hl num">1</span><span class=
"hl opt">).
</span><span class=
"hl kwd">toInt
</span><span class=
"hl opt">(),
</span> <span class=
"hl kwd">uint
</span><span class=
"hl opt">(
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">value
</span><span class=
"hl opt">(
</span><span class=
"hl num">2</span><span class=
"hl opt">).
</span><span class=
"hl kwd">toInt
</span><span class=
"hl opt">())));
</span>
324 mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">insert
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">,
</span> data
<span class=
"hl opt">);
</span>
325 <span class=
"hl opt">}
</span>
327 <span class=
"hl kwd">reset
</span><span class=
"hl opt">();
</span>
329 <span class=
"hl kwa">return true
</span><span class=
"hl opt">;
</span>
330 <span class=
"hl opt">}
</span></pre>
332 <p>Resetting the
<tt>QAbstractItemModel
</tt> data model here is ok, becase before loading any data the model is supposed to be
335 <p>Here is the complete
<tt>module.cpp
</tt> file:
337 <pre class=
"hl"><span class=
"hl com">/**
</span>
338 <span class=
"hl com"> *
@file PswGen/Storage/module.cpp
</span>
339 <span class=
"hl com"> */
</span>
341 <span class=
"hl ppc">#include
</span> <span class=
"hl pps">"module.h
"</span><span class=
"hl ppc"></span>
342 <span class=
"hl ppc">#include
</span> <span class=
"hl pps">"version.h
"</span><span class=
"hl ppc"></span>
344 <span class=
"hl ppc">#include
<Common/Globals
></span>
345 <span class=
"hl ppc">#include
<Common/iLogger
></span>
346 <span class=
"hl ppc">#include
<Common/iRegistry
></span>
347 <span class=
"hl ppc">#include
<Common/iApp
></span>
349 <span class=
"hl ppc">#include
<QtCore
></span>
350 <span class=
"hl ppc">#include
<QtSql/QtSql
></span>
352 <span class=
"hl kwd">VER_EXPORT_VERSION_INFO
</span><span class=
"hl opt">()
</span>
353 <span class=
"hl kwd">Q_EXPORT_PLUGIN2
</span><span class=
"hl opt">(
</span>VER_MODULE_NAME_STR
<span class=
"hl opt">,
</span> eVaf
<span class=
"hl opt">::
</span>PswGen
<span class=
"hl opt">::
</span>Storage
<span class=
"hl opt">::
</span>Module
<span class=
"hl opt">)
</span>
355 <span class=
"hl kwa">using namespace
</span> eVaf
<span class=
"hl opt">;
</span>
356 <span class=
"hl kwa">using namespace
</span> eVaf
<span class=
"hl opt">::
</span>PswGen
<span class=
"hl opt">;
</span>
357 <span class=
"hl kwa">using namespace
</span> eVaf
<span class=
"hl opt">::
</span>PswGen
<span class=
"hl opt">::
</span>Storage
<span class=
"hl opt">;
</span>
359 Module
<span class=
"hl opt">::
</span><span class=
"hl kwd">Module
</span><span class=
"hl opt">()
</span>
360 <span class=
"hl opt">:
</span> Plugins
<span class=
"hl opt">::
</span><span class=
"hl kwd">iPlugin
</span><span class=
"hl opt">()
</span>
361 <span class=
"hl opt">,
</span> <span class=
"hl kwd">mReady
</span><span class=
"hl opt">(
</span><span class=
"hl kwa">false
</span><span class=
"hl opt">)
</span>
362 <span class=
"hl opt">{
</span>
363 <span class=
"hl kwd">setObjectName
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">QString
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%
1.%
2"</span><span class=
"hl opt">).
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>VER_MODULE_NAME_STR
<span class=
"hl opt">).
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>__FUNCTION__
<span class=
"hl opt">));
</span>
365 mStorage
<span class=
"hl opt">=
</span> <span class=
"hl kwa">new
</span> Internal
<span class=
"hl opt">::
</span>StorageImpl
<span class=
"hl opt">;
</span>
367 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s created
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
368 <span class=
"hl opt">}
</span>
370 Module
<span class=
"hl opt">::~
</span><span class=
"hl kwd">Module
</span><span class=
"hl opt">()
</span>
371 <span class=
"hl opt">{
</span>
372 <span class=
"hl kwa">delete
</span> mStorage
<span class=
"hl opt">;
</span>
374 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s destroyed
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
375 <span class=
"hl opt">}
</span>
377 <span class=
"hl kwb">bool
</span> Module
<span class=
"hl opt">::
</span><span class=
"hl kwd">init
</span><span class=
"hl opt">(
</span>QString
<span class=
"hl kwb">const
</span> <span class=
"hl opt">&</span> args
<span class=
"hl opt">)
</span>
378 <span class=
"hl opt">{
</span>
379 <span class=
"hl kwd">Q_UNUSED
</span><span class=
"hl opt">(
</span>args
<span class=
"hl opt">);
</span>
381 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>mStorage
<span class=
"hl opt">-
></span><span class=
"hl kwd">init
</span><span class=
"hl opt">())
</span>
382 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
384 mReady
<span class=
"hl opt">=
</span> <span class=
"hl kwa">true
</span><span class=
"hl opt">;
</span>
386 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s initialized
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
388 <span class=
"hl kwa">return true
</span><span class=
"hl opt">;
</span>
389 <span class=
"hl opt">}
</span>
391 <span class=
"hl kwb">void
</span> Module
<span class=
"hl opt">::
</span><span class=
"hl kwd">done
</span><span class=
"hl opt">()
</span>
392 <span class=
"hl opt">{
</span>
393 mReady
<span class=
"hl opt">=
</span> <span class=
"hl kwa">false
</span><span class=
"hl opt">;
</span>
395 mStorage
<span class=
"hl opt">-
></span><span class=
"hl kwd">done
</span><span class=
"hl opt">();
</span>
397 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s finalized
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
398 <span class=
"hl opt">}
</span>
400 <span class=
"hl kwa">using namespace
</span> eVaf
<span class=
"hl opt">::
</span>PswGen
<span class=
"hl opt">::
</span>Storage
<span class=
"hl opt">::
</span>Internal
<span class=
"hl opt">;
</span>
402 <span class=
"hl kwb">char const
</span> <span class=
"hl opt">*
</span> <span class=
"hl kwb">const
</span> StorageImpl
<span class=
"hl opt">::
</span>DbConnectionName
<span class=
"hl opt">=
</span> <span class=
"hl str">"PswGenDB
"</span><span class=
"hl opt">;
</span>
404 <span class=
"hl kwb">char const
</span> <span class=
"hl opt">*
</span> <span class=
"hl kwb">const
</span> StorageImpl
<span class=
"hl opt">::
</span>DbName
<span class=
"hl opt">=
</span> <span class=
"hl str">"PswGen.sqlite
"</span><span class=
"hl opt">;
</span>
406 StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">StorageImpl
</span><span class=
"hl opt">()
</span>
407 <span class=
"hl opt">:
</span> <span class=
"hl kwd">QAbstractListModel
</span><span class=
"hl opt">()
</span>
408 <span class=
"hl opt">{
</span>
409 <span class=
"hl kwd">setObjectName
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">QString
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%
1.iGenerator
"</span><span class=
"hl opt">).
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>VER_MODULE_NAME_STR
<span class=
"hl opt">));
</span>
411 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s created
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
412 <span class=
"hl opt">}
</span>
414 StorageImpl
<span class=
"hl opt">::~
</span><span class=
"hl kwd">StorageImpl
</span><span class=
"hl opt">()
</span>
415 <span class=
"hl opt">{
</span>
416 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s destroyed
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
417 <span class=
"hl opt">}
</span>
419 <span class=
"hl kwb">bool
</span> StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">init
</span><span class=
"hl opt">()
</span>
420 <span class=
"hl opt">{
</span>
421 <span class=
"hl slc">// Open the database
</span>
422 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>QSqlDatabase
<span class=
"hl opt">::
</span><span class=
"hl kwd">contains
</span><span class=
"hl opt">(
</span>DbConnectionName
<span class=
"hl opt">)) {
</span>
423 <span class=
"hl slc">// No database connection yet
</span>
424 mDb
<span class=
"hl opt">=
</span> QSqlDatabase
<span class=
"hl opt">::
</span><span class=
"hl kwd">addDatabase
</span><span class=
"hl opt">(
</span><span class=
"hl str">"QSQLITE
"</span><span class=
"hl opt">,
</span> DbConnectionName
<span class=
"hl opt">);
</span>
425 mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">setDatabaseName
</span><span class=
"hl opt">(
</span>Common
<span class=
"hl opt">::
</span>iApp
<span class=
"hl opt">::
</span><span class=
"hl kwd">instance
</span><span class=
"hl opt">()-
></span><span class=
"hl kwd">dataRootDir
</span><span class=
"hl opt">() +
</span> DbName
<span class=
"hl opt">);
</span>
426 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">open
</span><span class=
"hl opt">()) {
</span>
427 QSqlError err
<span class=
"hl opt">=
</span> mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">lastError
</span><span class=
"hl opt">();
</span>
428 <span class=
"hl kwd">EVAF_ERROR
</span><span class=
"hl opt">(
</span><span class=
"hl str">"Failed to open database : %s
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>err
<span class=
"hl opt">.
</span><span class=
"hl kwd">text
</span><span class=
"hl opt">()));
</span>
429 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
430 <span class=
"hl opt">}
</span>
431 <span class=
"hl opt">}
</span>
432 <span class=
"hl kwa">else
</span> <span class=
"hl opt">{
</span>
433 <span class=
"hl slc">// Database connection already exists
</span>
434 mDb
<span class=
"hl opt">=
</span> QSqlDatabase
<span class=
"hl opt">::
</span><span class=
"hl kwd">database
</span><span class=
"hl opt">(
</span>DbConnectionName
<span class=
"hl opt">);
</span>
435 <span class=
"hl opt">}
</span>
437 <span class=
"hl slc">// Create tables if necessary
</span>
438 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span><span class=
"hl kwd">createTables
</span><span class=
"hl opt">())
</span>
439 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
441 <span class=
"hl slc">// Load data
</span>
442 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span><span class=
"hl kwd">loadData
</span><span class=
"hl opt">())
</span>
443 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
445 <span class=
"hl slc">/// Register our interface
</span>
446 Common
<span class=
"hl opt">::
</span>iRegistry
<span class=
"hl opt">::
</span><span class=
"hl kwd">instance
</span><span class=
"hl opt">()-
></span><span class=
"hl kwd">registerInterface
</span><span class=
"hl opt">(
</span><span class=
"hl str">"iStorage
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwa">this
</span><span class=
"hl opt">);
</span>
448 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s initialized
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
450 <span class=
"hl kwa">return true
</span><span class=
"hl opt">;
</span>
451 <span class=
"hl opt">}
</span>
453 <span class=
"hl kwb">void
</span> StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">done
</span><span class=
"hl opt">()
</span>
454 <span class=
"hl opt">{
</span>
455 mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">clear
</span><span class=
"hl opt">();
</span>
456 <span class=
"hl kwd">EVAF_INFO
</span><span class=
"hl opt">(
</span><span class=
"hl str">"%s finalized
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">objectName
</span><span class=
"hl opt">()));
</span>
457 <span class=
"hl opt">}
</span>
459 <span class=
"hl kwb">bool
</span> StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">save
</span><span class=
"hl opt">(
</span>QString
<span class=
"hl kwb">const
</span> <span class=
"hl opt">&</span> name
<span class=
"hl opt">,
</span> QExplicitlySharedDataPointer
<span class=
"hl opt"><</span>Storage
<span class=
"hl opt">::
</span>Data
<span class=
"hl opt">></span> data
<span class=
"hl opt">)
</span>
460 <span class=
"hl opt">{
</span>
461 <span class=
"hl kwd">EVAF_TEST_X
</span><span class=
"hl opt">(
</span>data
<span class=
"hl opt">,
</span> <span class=
"hl str">"Data cannot be null
"</span><span class=
"hl opt">);
</span>
462 <span class=
"hl kwd">EVAF_TEST_X
</span><span class=
"hl opt">(!
</span>name
<span class=
"hl opt">.
</span><span class=
"hl kwd">isEmpty
</span><span class=
"hl opt">(),
</span> <span class=
"hl str">"Name cannot be empty
"</span><span class=
"hl opt">);
</span>
464 <span class=
"hl slc">// Is it an update or a new data record?
</span>
465 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(
</span>mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">constFind
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">) !=
</span> mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">constEnd
</span><span class=
"hl opt">()) {
</span>
466 <span class=
"hl slc">// This is an update
</span>
467 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(
</span>data
<span class=
"hl opt">-
></span><span class=
"hl kwd">modified
</span><span class=
"hl opt">()) {
</span>
468 QSqlQuery
<span class=
"hl kwd">q
</span><span class=
"hl opt">(
</span>mDb
<span class=
"hl opt">);
</span>
469 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">exec
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">QString
</span><span class=
"hl opt">(
</span><span class=
"hl str">"UPDATE data SET length =
</span> <span class=
"hl esc">\'
</span><span class=
"hl str">%
1</span><span class=
"hl esc">\'
</span><span class=
"hl str">, flags =
</span> <span class=
"hl esc">\'
</span><span class=
"hl str">%
2</span><span class=
"hl esc">\'
</span> <span class=
"hl str">WHERE name =
</span> <span class=
"hl esc">\'
</span><span class=
"hl str">%
3</span><span class=
"hl esc">\'
</span><span class=
"hl str">;
"</span><span class=
"hl opt">)
</span>
470 <span class=
"hl opt">.
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>data
<span class=
"hl opt">-
></span><span class=
"hl kwd">length
</span><span class=
"hl opt">()).
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>data
<span class=
"hl opt">-
></span><span class=
"hl kwd">flags
</span><span class=
"hl opt">()).
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">))) {
</span>
471 QSqlError err
<span class=
"hl opt">=
</span> mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">lastError
</span><span class=
"hl opt">();
</span>
472 <span class=
"hl kwd">EVAF_ERROR
</span><span class=
"hl opt">(
</span><span class=
"hl str">"Failed to update
</span> <span class=
"hl esc">\'
</span><span class=
"hl str">%s
</span><span class=
"hl esc">\'
</span> <span class=
"hl str">: %s
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">),
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>err
<span class=
"hl opt">.
</span><span class=
"hl kwd">text
</span><span class=
"hl opt">()));
</span>
473 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
474 <span class=
"hl opt">}
</span>
475 <span class=
"hl opt">}
</span>
476 <span class=
"hl opt">}
</span>
477 <span class=
"hl kwa">else
</span> <span class=
"hl opt">{
</span>
478 <span class=
"hl slc">// Store to the database
</span>
479 QSqlQuery
<span class=
"hl kwd">q
</span><span class=
"hl opt">(
</span>mDb
<span class=
"hl opt">);
</span>
480 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">exec
</span><span class=
"hl opt">(
</span><span class=
"hl kwd">QString
</span><span class=
"hl opt">(
</span><span class=
"hl str">"INSERT INTO data (name, length, flags) VALUES (
</span><span class=
"hl esc">\'
</span><span class=
"hl str">%
1</span><span class=
"hl esc">\'
</span><span class=
"hl str">, %
2, %
3);
"</span><span class=
"hl opt">)
</span>
481 <span class=
"hl opt">.
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">).
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span>data
<span class=
"hl opt">-
></span><span class=
"hl kwd">length
</span><span class=
"hl opt">())
</span>
482 <span class=
"hl opt">.
</span><span class=
"hl kwd">arg
</span><span class=
"hl opt">(
</span><span class=
"hl kwb">int
</span><span class=
"hl opt">(
</span>data
<span class=
"hl opt">-
></span><span class=
"hl kwd">flags
</span><span class=
"hl opt">())))) {
</span>
483 QSqlError err
<span class=
"hl opt">=
</span> mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">lastError
</span><span class=
"hl opt">();
</span>
484 <span class=
"hl kwd">EVAF_ERROR
</span><span class=
"hl opt">(
</span><span class=
"hl str">"Failed to insert
</span> <span class=
"hl esc">\'
</span><span class=
"hl str">%s
</span><span class=
"hl esc">\'
</span> <span class=
"hl str">: %s
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">),
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>err
<span class=
"hl opt">.
</span><span class=
"hl kwd">text
</span><span class=
"hl opt">()));
</span>
485 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
486 <span class=
"hl opt">}
</span>
488 <span class=
"hl slc">// Store also into the local hash
</span>
489 mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">insert
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">,
</span> data
<span class=
"hl opt">);
</span>
491 <span class=
"hl slc">// Reset the model
</span>
492 <span class=
"hl kwd">reset
</span><span class=
"hl opt">();
</span>
493 <span class=
"hl opt">}
</span>
495 data
<span class=
"hl opt">-
></span><span class=
"hl kwd">reset
</span><span class=
"hl opt">();
</span>
497 <span class=
"hl kwa">return true
</span><span class=
"hl opt">;
</span>
498 <span class=
"hl opt">}
</span>
500 QExplicitlySharedDataPointer
<span class=
"hl opt"><</span>Storage
<span class=
"hl opt">::
</span>Data
<span class=
"hl opt">></span> StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">query
</span><span class=
"hl opt">(
</span>QString
<span class=
"hl kwb">const
</span> <span class=
"hl opt">&</span> name
<span class=
"hl opt">)
</span> <span class=
"hl kwb">const
</span>
501 <span class=
"hl opt">{
</span>
502 QMap
<span class=
"hl opt"><</span>QString
<span class=
"hl opt">,
</span> QExplicitlySharedDataPointer
<span class=
"hl opt"><</span>Storage
<span class=
"hl opt">::
</span>Data
<span class=
"hl opt">> >::
</span>const_iterator it
<span class=
"hl opt">=
</span> mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">constFind
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">);
</span>
503 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(
</span>it
<span class=
"hl opt">!=
</span> mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">constEnd
</span><span class=
"hl opt">())
</span>
504 <span class=
"hl kwa">return
</span> it
<span class=
"hl opt">.
</span><span class=
"hl kwd">value
</span><span class=
"hl opt">();
</span>
505 <span class=
"hl kwa">else
</span>
506 <span class=
"hl kwa">return
</span> QExplicitlySharedDataPointer
<span class=
"hl opt"><</span>Storage
<span class=
"hl opt">::
</span>Data
<span class=
"hl opt">>();
</span>
507 <span class=
"hl opt">}
</span>
509 QVariant StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">data
</span><span class=
"hl opt">(
</span>QModelIndex
<span class=
"hl kwb">const
</span> <span class=
"hl opt">&</span> index
<span class=
"hl opt">,
</span> <span class=
"hl kwb">int
</span> role
<span class=
"hl opt">)
</span> <span class=
"hl kwb">const
</span>
510 <span class=
"hl opt">{
</span>
511 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>index
<span class=
"hl opt">.
</span><span class=
"hl kwd">isValid
</span><span class=
"hl opt">() ||
</span> index
<span class=
"hl opt">.
</span><span class=
"hl kwd">row
</span><span class=
"hl opt">()
<</span> <span class=
"hl num">0</span> <span class=
"hl opt">||
</span> index
<span class=
"hl opt">.
</span><span class=
"hl kwd">row
</span><span class=
"hl opt">()
>=
</span> mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">size
</span><span class=
"hl opt">() ||
</span> index
<span class=
"hl opt">.
</span><span class=
"hl kwd">column
</span><span class=
"hl opt">() !=
</span> <span class=
"hl num">0</span><span class=
"hl opt">)
</span>
512 <span class=
"hl kwa">return
</span> <span class=
"hl kwd">QVariant
</span><span class=
"hl opt">();
</span>
514 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(
</span>role
<span class=
"hl opt">==
</span> Qt
<span class=
"hl opt">::
</span>EditRole
<span class=
"hl opt">||
</span> role
<span class=
"hl opt">==
</span> Qt
<span class=
"hl opt">::
</span>DisplayRole
<span class=
"hl opt">)
</span>
515 <span class=
"hl kwa">return
</span> mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">keys
</span><span class=
"hl opt">().
</span><span class=
"hl kwd">at
</span><span class=
"hl opt">(
</span>index
<span class=
"hl opt">.
</span><span class=
"hl kwd">row
</span><span class=
"hl opt">());
</span>
517 <span class=
"hl kwa">return
</span> <span class=
"hl kwd">QVariant
</span><span class=
"hl opt">();
</span>
518 <span class=
"hl opt">}
</span>
520 <span class=
"hl kwb">bool
</span> StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">createTables
</span><span class=
"hl opt">()
</span>
521 <span class=
"hl opt">{
</span>
522 QSqlQuery
<span class=
"hl kwd">q
</span><span class=
"hl opt">(
</span>mDb
<span class=
"hl opt">);
</span>
523 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">exec
</span><span class=
"hl opt">(
</span><span class=
"hl str">"SELECT name FROM sqlite_master WHERE type=
</span><span class=
"hl esc">\'
</span><span class=
"hl str">table
</span><span class=
"hl esc">\'
</span> <span class=
"hl str">AND name=
</span><span class=
"hl esc">\'
</span><span class=
"hl str">data
</span><span class=
"hl esc">\'
</span><span class=
"hl str">;
"</span><span class=
"hl opt">)) {
</span>
524 QSqlError err
<span class=
"hl opt">=
</span> mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">lastError
</span><span class=
"hl opt">();
</span>
525 <span class=
"hl kwd">EVAF_ERROR
</span><span class=
"hl opt">(
</span><span class=
"hl str">"Failed to query database : %s
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>err
<span class=
"hl opt">.
</span><span class=
"hl kwd">text
</span><span class=
"hl opt">()));
</span>
526 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
527 <span class=
"hl opt">}
</span>
529 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">isActive
</span><span class=
"hl opt">()
&&</span> q
<span class=
"hl opt">.
</span><span class=
"hl kwd">isSelect
</span><span class=
"hl opt">()
&&</span> q
<span class=
"hl opt">.
</span><span class=
"hl kwd">first
</span><span class=
"hl opt">())
</span>
530 <span class=
"hl kwa">return true
</span><span class=
"hl opt">;
</span> <span class=
"hl slc">// We already have a table called 'data'
</span>
532 <span class=
"hl slc">// Create the 'data' table
</span>
533 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">exec
</span><span class=
"hl opt">(
</span><span class=
"hl str">"CREATE TABLE data (name text primary key not null, length integer, flags integer);
"</span><span class=
"hl opt">)) {
</span>
534 QSqlError err
<span class=
"hl opt">=
</span> mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">lastError
</span><span class=
"hl opt">();
</span>
535 <span class=
"hl kwd">EVAF_ERROR
</span><span class=
"hl opt">(
</span><span class=
"hl str">"Failed to create table
</span> <span class=
"hl esc">\'
</span><span class=
"hl str">data
</span><span class=
"hl esc">\'
</span> <span class=
"hl str">: %s
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>err
<span class=
"hl opt">.
</span><span class=
"hl kwd">text
</span><span class=
"hl opt">()));
</span>
536 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
537 <span class=
"hl opt">}
</span>
539 <span class=
"hl kwa">return true
</span><span class=
"hl opt">;
</span>
540 <span class=
"hl opt">}
</span>
542 <span class=
"hl kwb">bool
</span> StorageImpl
<span class=
"hl opt">::
</span><span class=
"hl kwd">loadData
</span><span class=
"hl opt">()
</span>
543 <span class=
"hl opt">{
</span>
544 QSqlQuery
<span class=
"hl kwd">q
</span><span class=
"hl opt">(
</span>mDb
<span class=
"hl opt">);
</span>
545 <span class=
"hl kwa">if
</span> <span class=
"hl opt">(!
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">exec
</span><span class=
"hl opt">(
</span><span class=
"hl str">"SELECT name, length, flags FROM data;
"</span><span class=
"hl opt">)) {
</span>
546 QSqlError err
<span class=
"hl opt">=
</span> mDb
<span class=
"hl opt">.
</span><span class=
"hl kwd">lastError
</span><span class=
"hl opt">();
</span>
547 <span class=
"hl kwd">EVAF_ERROR
</span><span class=
"hl opt">(
</span><span class=
"hl str">"Failed to query database : %s
"</span><span class=
"hl opt">,
</span> <span class=
"hl kwd">qPrintable
</span><span class=
"hl opt">(
</span>err
<span class=
"hl opt">.
</span><span class=
"hl kwd">text
</span><span class=
"hl opt">()));
</span>
548 <span class=
"hl kwa">return false
</span><span class=
"hl opt">;
</span>
549 <span class=
"hl opt">}
</span>
551 <span class=
"hl kwa">while
</span> <span class=
"hl opt">(
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">next
</span><span class=
"hl opt">()) {
</span>
552 QString name
<span class=
"hl opt">=
</span> q
<span class=
"hl opt">.
</span><span class=
"hl kwd">value
</span><span class=
"hl opt">(
</span><span class=
"hl num">0</span><span class=
"hl opt">).
</span><span class=
"hl kwd">toString
</span><span class=
"hl opt">();
</span>
553 QExplicitlySharedDataPointer
<span class=
"hl opt"><</span>Storage
<span class=
"hl opt">::
</span>Data
<span class=
"hl opt">></span> <span class=
"hl kwd">data
</span><span class=
"hl opt">(
</span><span class=
"hl kwa">new
</span> Storage
<span class=
"hl opt">::
</span><span class=
"hl kwd">Data
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">,
</span> q
<span class=
"hl opt">.
</span><span class=
"hl kwd">value
</span><span class=
"hl opt">(
</span><span class=
"hl num">1</span><span class=
"hl opt">).
</span><span class=
"hl kwd">toInt
</span><span class=
"hl opt">(),
</span> <span class=
"hl kwd">uint
</span><span class=
"hl opt">(
</span>q
<span class=
"hl opt">.
</span><span class=
"hl kwd">value
</span><span class=
"hl opt">(
</span><span class=
"hl num">2</span><span class=
"hl opt">).
</span><span class=
"hl kwd">toInt
</span><span class=
"hl opt">())));
</span>
554 mData
<span class=
"hl opt">.
</span><span class=
"hl kwd">insert
</span><span class=
"hl opt">(
</span>name
<span class=
"hl opt">,
</span> data
<span class=
"hl opt">);
</span>
555 <span class=
"hl opt">}
</span>
557 <span class=
"hl kwd">reset
</span><span class=
"hl opt">();
</span>
559 <span class=
"hl kwa">return true
</span><span class=
"hl opt">;
</span>
560 <span class=
"hl opt">}
</span></pre>
562 <p>Next --
<a href=
"pswgen08.html">Building Storage Module
</a>.
</p>