]> vaikene.ee Git - evaf/blob - www/pswgen07.html
Warning fixes and copyright update.
[evaf] / www / pswgen07.html
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">
3
4 <head>
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" />
12 </head>
13
14 <body>
15
16 <p>Next: <a href="pswgen08.html">08 - Building Storage Module</a>, Previous: <a href="pswgen06.html">06 - Storage Module</a></p>
17
18 <h1>eVaf Tutorial</h1>
19
20 <h2>07 - Storage Module</h2>
21
22 <p>Create the <tt>module.cpp</tt> file in the <tt>src/apps/PswGen/Storage</tt> directory:</tt>
23
24 <pre class="hl"><span class="hl com">/**</span>
25 <span class="hl com"> * &#64;file PswGen/Storage/module.cpp</span>
26 <span class="hl com"> */</span>
27
28 <span class="hl ppc">#include</span> <span class="hl pps">&quot;module.h&quot;</span><span class="hl ppc"></span>
29 <span class="hl ppc">#include &lt;QtCore&gt;</span></pre>
30
31 <p>Copy version information files from the <tt>Generator</tt> module:</p>
32
33 <pre>evaf/src/apps/PswGen/Storage $ <code>cp ../Generator/version.{h,rc} .</code></pre>
34
35 <p>Modify the <tt>version.h</tt> file:</p>
36
37 <pre class="hl"><span class="hl com">/**</span>
38 <span class="hl com"> * &#64;file PswGen/Storage/version.h</span>
39 <span class="hl com"> */</span>
40
41 <span class="hl ppc">#ifndef __PSWGEN_STORAGE_VERSION_H</span>
42 <span class="hl ppc">#define __PSWGEN_STORAGE_VERSION_H</span>
43
44 <span class="hl ppc">#include &lt;version_rc.h&gt;</span>
45
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>
50
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">&quot;0.1.1.1\0&quot;</span><span class="hl ppc"></span>
55
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">&quot;PswStorage\0&quot;</span><span class="hl ppc"></span>
60
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>
65
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>
70
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">&quot;PswStorage.dll\0&quot;</span><span class="hl ppc"></span>
75
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">&quot;Module that stores data for generating strong passwords.\0&quot;</span><span class="hl ppc"></span>
80
81 <span class="hl ppc">#endif</span> <span class="hl slc">// version.h</span><span class="hl ppc"></span></pre>
82
83 <p>Include the <tt>version.h</tt> header file in <tt>module.cpp</tt> and export version information:</p>
84
85 <pre class="hl">
86 <span class="hl ppc">#include</span> <span class="hl pps">&quot;version.h&quot;</span><span class="hl ppc"></span>
87
88 <span class="hl kwd">VER_EXPORT_VERSION_INFO</span><span class="hl opt">()</span></pre>
89
90 <p>Make it a proper Qt plugin by using the <tt>Q_EXPORT_PLUGIN2()</tt> macro:</p>
91
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>
93
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>
97
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>
100
101 <p>The rest of the code sets the name of the object and outputs info messages.</p>
102
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">&quot;%1.%2&quot;</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>
108
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>
110
111 <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">&quot;%s created&quot;</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>
113
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>
117
118 <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">&quot;%s destroyed&quot;</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>
120
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">&amp;</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>
124
125 <span class="hl kwa">if</span> <span class="hl opt">(!</span>mStorage<span class="hl opt">-&gt;</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>
127
128 mReady <span class="hl opt">=</span> <span class="hl kwa">true</span><span class="hl opt">;</span>
129
130 <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">&quot;%s initialized&quot;</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>
131
132 <span class="hl kwa">return true</span><span class="hl opt">;</span>
133 <span class="hl opt">}</span>
134
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>
138
139 mStorage<span class="hl opt">-&gt;</span><span class="hl kwd">done</span><span class="hl opt">();</span>
140
141 <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">&quot;%s finalized&quot;</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>
143
144 <p>The <tt>StorageImpl</tt> class does very little in the constructor and in the destructor:</p>
145
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">&quot;%1.iGenerator&quot;</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>
150
151 <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">&quot;%s created&quot;</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>
153
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">&quot;%s destroyed&quot;</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>
158
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>
162
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
164 located.</p>
165
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">&quot;QSQLITE&quot;</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">()-&gt;</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">&quot;Failed to open database : %s&quot;</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>
183
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>
187
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>
191
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">()-&gt;</span><span class="hl kwd">registerInterface</span><span class="hl opt">(</span><span class="hl str">&quot;iStorage&quot;</span><span class="hl opt">,</span> <span class="hl kwa">this</span><span class="hl opt">);</span>
194
195 <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">&quot;%s initialized&quot;</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>
196
197 <span class="hl kwa">return true</span><span class="hl opt">;</span>
198 <span class="hl opt">}</span></pre>
199
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>
202
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">&quot;%s finalized&quot;</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>
208
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>
211
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">&amp;</span> name<span class="hl opt">,</span> QExplicitlySharedDataPointer<span class="hl opt">&lt;</span>Storage<span class="hl opt">::</span>Data<span class="hl opt">&gt;</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">&quot;Data cannot be null&quot;</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">&quot;Name cannot be empty&quot;</span><span class="hl opt">);</span>
216
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">-&gt;</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">&quot;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">;&quot;</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">-&gt;</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">-&gt;</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">&quot;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&quot;</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">&quot;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);&quot;</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">-&gt;</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">-&gt;</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">&quot;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&quot;</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>
240
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>
243
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>
247
248 data<span class="hl opt">-&gt;</span><span class="hl kwd">reset</span><span class="hl opt">();</span>
249
250 <span class="hl kwa">return true</span><span class="hl opt">;</span>
251 <span class="hl opt">}</span></pre>
252
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>
257
258 <p>Querying data is much simpler thanks to the internal <tt>QMap</tt> container:</p>
259
260 <pre class="hl">QExplicitlySharedDataPointer<span class="hl opt">&lt;</span>Storage<span class="hl opt">::</span>Data<span class="hl opt">&gt;</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">&amp;</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">&lt;</span>QString<span class="hl opt">,</span> QExplicitlySharedDataPointer<span class="hl opt">&lt;</span>Storage<span class="hl opt">::</span>Data<span class="hl opt">&gt; &gt;::</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">&lt;</span>Storage<span class="hl opt">::</span>Data<span class="hl opt">&gt;();</span>
267 <span class="hl opt">}</span></pre>
268
269 <p>We return an empty <tt>QExplicitlySharedDataPointer</tt> object if no data objects with the given name exists.</p>
270
271 <p>The <tt>data()</tt> method returns names of data objects for the <tt>QCompleter</tt> auto completion list of words:</p>
272
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">&amp;</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">() &lt;</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">() &gt;=</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>
277
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>
280
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>
283
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>
287
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">&quot;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">;&quot;</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">&quot;Failed to query database : %s&quot;</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>
296
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">() &amp;&amp;</span> q<span class="hl opt">.</span><span class="hl kwd">isSelect</span><span class="hl opt">() &amp;&amp;</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>
299
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">&quot;CREATE TABLE data (name text primary key not null, length integer, flags integer);&quot;</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">&quot;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&quot;</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>
306
307 <span class="hl kwa">return true</span><span class="hl opt">;</span>
308 <span class="hl opt">}</span></pre>
309
310 <p>Finally, the <tt>loadData()</tt> method loads all the data records from the database to the memory:</p>
311
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">&quot;SELECT name, length, flags FROM data;&quot;</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">&quot;Failed to query database : %s&quot;</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>
320
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">&lt;</span>Storage<span class="hl opt">::</span>Data<span class="hl opt">&gt;</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>
326
327 <span class="hl kwd">reset</span><span class="hl opt">();</span>
328
329 <span class="hl kwa">return true</span><span class="hl opt">;</span>
330 <span class="hl opt">}</span></pre>
331
332 <p>Resetting the <tt>QAbstractItemModel</tt> data model here is ok, becase before loading any data the model is supposed to be
333 empty.</p>
334
335 <p>Here is the complete <tt>module.cpp</tt> file:
336
337 <pre class="hl"><span class="hl com">/**</span>
338 <span class="hl com"> * &#64;file PswGen/Storage/module.cpp</span>
339 <span class="hl com"> */</span>
340
341 <span class="hl ppc">#include</span> <span class="hl pps">&quot;module.h&quot;</span><span class="hl ppc"></span>
342 <span class="hl ppc">#include</span> <span class="hl pps">&quot;version.h&quot;</span><span class="hl ppc"></span>
343
344 <span class="hl ppc">#include &lt;Common/Globals&gt;</span>
345 <span class="hl ppc">#include &lt;Common/iLogger&gt;</span>
346 <span class="hl ppc">#include &lt;Common/iRegistry&gt;</span>
347 <span class="hl ppc">#include &lt;Common/iApp&gt;</span>
348
349 <span class="hl ppc">#include &lt;QtCore&gt;</span>
350 <span class="hl ppc">#include &lt;QtSql/QtSql&gt;</span>
351
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>
354
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>
358
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">&quot;%1.%2&quot;</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>
364
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>
366
367 <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">&quot;%s created&quot;</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>
369
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>
373
374 <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">&quot;%s destroyed&quot;</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>
376
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">&amp;</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>
380
381 <span class="hl kwa">if</span> <span class="hl opt">(!</span>mStorage<span class="hl opt">-&gt;</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>
383
384 mReady <span class="hl opt">=</span> <span class="hl kwa">true</span><span class="hl opt">;</span>
385
386 <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">&quot;%s initialized&quot;</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>
387
388 <span class="hl kwa">return true</span><span class="hl opt">;</span>
389 <span class="hl opt">}</span>
390
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>
394
395 mStorage<span class="hl opt">-&gt;</span><span class="hl kwd">done</span><span class="hl opt">();</span>
396
397 <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">&quot;%s finalized&quot;</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>
399
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>
401
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">&quot;PswGenDB&quot;</span><span class="hl opt">;</span>
403
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">&quot;PswGen.sqlite&quot;</span><span class="hl opt">;</span>
405
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">&quot;%1.iGenerator&quot;</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>
410
411 <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">&quot;%s created&quot;</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>
413
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">&quot;%s destroyed&quot;</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>
418
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">&quot;QSQLITE&quot;</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">()-&gt;</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">&quot;Failed to open database : %s&quot;</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>
436
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>
440
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>
444
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">()-&gt;</span><span class="hl kwd">registerInterface</span><span class="hl opt">(</span><span class="hl str">&quot;iStorage&quot;</span><span class="hl opt">,</span> <span class="hl kwa">this</span><span class="hl opt">);</span>
447
448 <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">&quot;%s initialized&quot;</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>
449
450 <span class="hl kwa">return true</span><span class="hl opt">;</span>
451 <span class="hl opt">}</span>
452
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">&quot;%s finalized&quot;</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>
458
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">&amp;</span> name<span class="hl opt">,</span> QExplicitlySharedDataPointer<span class="hl opt">&lt;</span>Storage<span class="hl opt">::</span>Data<span class="hl opt">&gt;</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">&quot;Data cannot be null&quot;</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">&quot;Name cannot be empty&quot;</span><span class="hl opt">);</span>
463
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">-&gt;</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">&quot;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">;&quot;</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">-&gt;</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">-&gt;</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">&quot;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&quot;</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">&quot;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);&quot;</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">-&gt;</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">-&gt;</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">&quot;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&quot;</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>
487
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>
490
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>
494
495 data<span class="hl opt">-&gt;</span><span class="hl kwd">reset</span><span class="hl opt">();</span>
496
497 <span class="hl kwa">return true</span><span class="hl opt">;</span>
498 <span class="hl opt">}</span>
499
500 QExplicitlySharedDataPointer<span class="hl opt">&lt;</span>Storage<span class="hl opt">::</span>Data<span class="hl opt">&gt;</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">&amp;</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">&lt;</span>QString<span class="hl opt">,</span> QExplicitlySharedDataPointer<span class="hl opt">&lt;</span>Storage<span class="hl opt">::</span>Data<span class="hl opt">&gt; &gt;::</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">&lt;</span>Storage<span class="hl opt">::</span>Data<span class="hl opt">&gt;();</span>
507 <span class="hl opt">}</span>
508
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">&amp;</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">() &lt;</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">() &gt;=</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>
513
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>
516
517 <span class="hl kwa">return</span> <span class="hl kwd">QVariant</span><span class="hl opt">();</span>
518 <span class="hl opt">}</span>
519
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">&quot;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">;&quot;</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">&quot;Failed to query database : %s&quot;</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>
528
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">() &amp;&amp;</span> q<span class="hl opt">.</span><span class="hl kwd">isSelect</span><span class="hl opt">() &amp;&amp;</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>
531
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">&quot;CREATE TABLE data (name text primary key not null, length integer, flags integer);&quot;</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">&quot;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&quot;</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>
538
539 <span class="hl kwa">return true</span><span class="hl opt">;</span>
540 <span class="hl opt">}</span>
541
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">&quot;SELECT name, length, flags FROM data;&quot;</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">&quot;Failed to query database : %s&quot;</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>
550
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">&lt;</span>Storage<span class="hl opt">::</span>Data<span class="hl opt">&gt;</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>
556
557 <span class="hl kwd">reset</span><span class="hl opt">();</span>
558
559 <span class="hl kwa">return true</span><span class="hl opt">;</span>
560 <span class="hl opt">}</span></pre>
561
562 <p>Next -- <a href="pswgen08.html">Building Storage Module</a>.</p>
563
564 </body>
565 </html>