]> vaikene.ee Git - evaf/blob - www/pswgen07.html
Added more information about shared data objects.
[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 <h1>eVaf Tutorial</h1>
17
18 <h2>07 - Storage Module</h2>
19
20 <p>Create the <tt>module.cpp</tt> file in the <tt>src/apps/PswGen/Storage</tt> directory:</tt>
21
22 <pre class="hl"><span class="hl com">/**</span>
23 <span class="hl com"> * &#64;file PswGen/Storage/module.cpp</span>
24 <span class="hl com"> */</span>
25
26 <span class="hl ppc">#include</span> <span class="hl pps">&quot;module.h&quot;</span><span class="hl ppc"></span>
27 <span class="hl ppc">#include &lt;QtCore&gt;</span></pre>
28
29 <p>Copy version information files from the <tt>Generator<tt> module:</p>
30
31 <pre>evaf/src/apps/PswGen/Storage $ <code>cp ../Generator/version.{h,rc} .</code></pre>
32
33 <p>Modify the <tt>version.h</tt> file:</p>
34
35 <pre class="hl"><span class="hl com">/**</span>
36 <span class="hl com"> * &#64;file PswGen/Storage/version.h</span>
37 <span class="hl com"> */</span>
38
39 <span class="hl ppc">#ifndef __PSWGEN_STORAGE_VERSION_H</span>
40 <span class="hl ppc">#define __PSWGEN_STORAGE_VERSION_H</span>
41
42 <span class="hl ppc">#include &lt;version_rc.h&gt;</span>
43
44 <span class="hl com">/**</span>
45 <span class="hl com"> * Module/library version number in the form major,minor,release,build</span>
46 <span class="hl com"> */</span>
47 <span class="hl ppc">#define VER_FILE_VERSION 0,1,1,1</span>
48
49 <span class="hl com">/**</span>
50 <span class="hl com"> * Module/library version number in the string format (shall end with \0)</span>
51 <span class="hl com"> */</span>
52 <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>
53
54 <span class="hl com">/**</span>
55 <span class="hl com"> * Module/library name (shall end with \0)</span>
56 <span class="hl com"> */</span>
57 <span class="hl ppc">#define VER_MODULE_NAME_STR</span> <span class="hl pps">&quot;PswStorage\0&quot;</span><span class="hl ppc"></span>
58
59 <span class="hl com">/**</span>
60 <span class="hl com"> * Module type (see version_rc.h for all the types)</span>
61 <span class="hl com"> */</span>
62 <span class="hl ppc">#define VER_MODULE_TYPE MT_GENERIC</span>
63
64 <span class="hl com">/**</span>
65 <span class="hl com"> * Module type in the string format (see version_rc for all the types)</span>
66 <span class="hl com"> */</span>
67 <span class="hl ppc">#define VER_MODULE_TYPE_STR MT_GENERIC</span>
68
69 <span class="hl com">/**</span>
70 <span class="hl com"> * Original file name for windows (shall end with \0)</span>
71 <span class="hl com"> */</span>
72 <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>
73
74 <span class="hl com">/**</span>
75 <span class="hl com"> * Description of the module/library (shall end with \0)</span>
76 <span class="hl com"> */</span>
77 <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>
78
79 <span class="hl ppc">#endif</span> <span class="hl slc">// version.h</span><span class="hl ppc"></span></pre>
80
81 <p>Include the <tt>version.h</tt> header file in <tt>module.cpp</tt> and export version information:</p>
82
83 <pre class="hl">
84 <span class="hl ppc">#include</span> <span class="hl pps">&quot;version.h&quot;</span><span class="hl ppc"></span>
85
86 <span class="hl kwd">VER_EXPORT_VERSION_INFO</span><span class="hl opt">()</span></pre>
87
88 <p>Make it a proper Qt plugin by using the <tt>Q_EXPORT_PLUGIN2()</tt> macro:</p>
89
90 <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>
91
92 <p>The <tt>Module</tt> class creates the internal <tt>StorageImpl</tt> object in the constructor, but initializes it in the
93 <tt>init()</tt> method. This way we can return errors from the module if initialization fails. Similarly, we finalize the
94 internal <tt>StorageImpl</tt> object in the <tt>done()</tt> method and delete in the destructor.</p>
95
96 <p>The module is ready when the internal <tt>StorageImpl</tt> object is initalized and we set the <tt>mReady</tt> flag to
97 <tt>true</tt> when the initialization is done and back to <tt>false</tt> in the <tt>done()</tt> method.</p>
98
99 <p>The rest of the code sets the name of the object and outputs info messages.</p>
100
101 <pre class="hl">Module<span class="hl opt">::</span><span class="hl kwd">Module</span><span class="hl opt">()</span>
102 <span class="hl opt">:</span> Plugins<span class="hl opt">::</span><span class="hl kwd">iPlugin</span><span class="hl opt">()</span>
103 <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>
104 <span class="hl opt">{</span>
105 <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>
106
107 mStorage <span class="hl opt">=</span> <span class="hl kwa">new</span> Internal<span class="hl opt">::</span>StorageImpl<span class="hl opt">;</span>
108
109 <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>
110 <span class="hl opt">}</span>
111
112 Module<span class="hl opt">::~</span><span class="hl kwd">Module</span><span class="hl opt">()</span>
113 <span class="hl opt">{</span>
114 <span class="hl kwa">delete</span> mStorage<span class="hl opt">;</span>
115
116 <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>
117 <span class="hl opt">}</span>
118
119 <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>
120 <span class="hl opt">{</span>
121 <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>args<span class="hl opt">);</span>
122
123 <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>
124 <span class="hl kwa">return false</span><span class="hl opt">;</span>
125
126 mReady <span class="hl opt">=</span> <span class="hl kwa">true</span><span class="hl opt">;</span>
127
128 <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>
129
130 <span class="hl kwa">return true</span><span class="hl opt">;</span>
131 <span class="hl opt">}</span>
132
133 <span class="hl kwb">void</span> Module<span class="hl opt">::</span><span class="hl kwd">done</span><span class="hl opt">()</span>
134 <span class="hl opt">{</span>
135 mReady <span class="hl opt">=</span> <span class="hl kwa">false</span><span class="hl opt">;</span>
136
137 mStorage<span class="hl opt">-&gt;</span><span class="hl kwd">done</span><span class="hl opt">();</span>
138
139 <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>
140 <span class="hl opt">}</span></pre>
141
142 <p>The <tt>StorageImpl</tt> class does very little in the constructor and in the destructor:</p>
143
144 <pre class="hl">StorageImpl<span class="hl opt">::</span><span class="hl kwd">StorageImpl</span><span class="hl opt">()</span>
145 <span class="hl opt">:</span> <span class="hl kwd">QAbstractListModel</span><span class="hl opt">()</span>
146 <span class="hl opt">{</span>
147 <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>
148
149 <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>
150 <span class="hl opt">}</span>
151
152 StorageImpl<span class="hl opt">::~</span><span class="hl kwd">StorageImpl</span><span class="hl opt">()</span>
153 <span class="hl opt">{</span>
154 <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>
155 <span class="hl opt">}</span></pre>
156
157 <p>Initialization of the <tt>StorageImpl</tt> class happens in the <tt>init()</tt> method, where we open the database connection,
158 create tables if necessary and load data from the database. We also register the <tt>iStorage</tt> interface in the global
159 registry of interfaces.</p>
160
161 <p>We use the <tt>Common::iApp</tt> interface to find the data root directory where the SQLITE database file is going to be
162 located.</p>
163
164 <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>
165 <span class="hl opt">{</span>
166 <span class="hl slc">// Open the database</span>
167 <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>
168 <span class="hl slc">// No database connection yet</span>
169 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>
170 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>
171 <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>
172 QSqlError err <span class="hl opt">=</span> mDb<span class="hl opt">.</span><span class="hl kwd">lastError</span><span class="hl opt">();</span>
173 <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>
174 <span class="hl kwa">return false</span><span class="hl opt">;</span>
175 <span class="hl opt">}</span>
176 <span class="hl opt">}</span>
177 <span class="hl kwa">else</span> <span class="hl opt">{</span>
178 <span class="hl slc">// Database connection already exists</span>
179 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>
180 <span class="hl opt">}</span>
181
182 <span class="hl slc">// Create tables if necessary</span>
183 <span class="hl kwa">if</span> <span class="hl opt">(!</span><span class="hl kwd">createTables</span><span class="hl opt">())</span>
184 <span class="hl kwa">return false</span><span class="hl opt">;</span>
185
186 <span class="hl slc">// Load data</span>
187 <span class="hl kwa">if</span> <span class="hl opt">(!</span><span class="hl kwd">loadData</span><span class="hl opt">())</span>
188 <span class="hl kwa">return false</span><span class="hl opt">;</span>
189
190 <span class="hl slc">/// Register our interface</span>
191 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>
192
193 <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>
194
195 <span class="hl kwa">return true</span><span class="hl opt">;</span>
196 <span class="hl opt">}</span></pre>
197
198 <p>The finalization of the <tt>StorageImpl</tt> class happens in the <tt>done()</tt> method, where we only need to clear the list
199 of shared data objects:</p>
200
201 <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>
202 <span class="hl opt">{</span>
203 mData<span class="hl opt">.</span><span class="hl kwd">clear</span><span class="hl opt">();</span>
204 <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>
205 <span class="hl opt">}</span></pre>
206
207 <p>The <tt>StorageImpl::save()</tt> method verifies that the shared data object is valid and the name not empty. Then it either
208 adds a new data record to the database or updates an existing one.</p>
209
210 <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>
211 <span class="hl opt">{</span>
212 <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>
213 <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>
214
215 <span class="hl slc">// Is it an update or a new data record?</span>
216 <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>
217 <span class="hl slc">// This is an update</span>
218 <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>
219 QSqlQuery <span class="hl kwd">q</span><span class="hl opt">(</span>mDb<span class="hl opt">);</span>
220 <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>
221 <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>
222 QSqlError err <span class="hl opt">=</span> mDb<span class="hl opt">.</span><span class="hl kwd">lastError</span><span class="hl opt">();</span>
223 <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>
224 <span class="hl kwa">return false</span><span class="hl opt">;</span>
225 <span class="hl opt">}</span>
226 <span class="hl opt">}</span>
227 <span class="hl opt">}</span>
228 <span class="hl kwa">else</span> <span class="hl opt">{</span>
229 <span class="hl slc">// Store to the database</span>
230 QSqlQuery <span class="hl kwd">q</span><span class="hl opt">(</span>mDb<span class="hl opt">);</span>
231 <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>
232 <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>
233 <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>
234 QSqlError err <span class="hl opt">=</span> mDb<span class="hl opt">.</span><span class="hl kwd">lastError</span><span class="hl opt">();</span>
235 <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>
236 <span class="hl kwa">return false</span><span class="hl opt">;</span>
237 <span class="hl opt">}</span>
238
239 <span class="hl slc">// Store also into the local hash</span>
240 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>
241
242 <span class="hl slc">// Reset the model</span>
243 <span class="hl kwd">reset</span><span class="hl opt">();</span>
244 <span class="hl opt">}</span>
245
246 data<span class="hl opt">-&gt;</span><span class="hl kwd">reset</span><span class="hl opt">();</span>
247
248 <span class="hl kwa">return true</span><span class="hl opt">;</span>
249 <span class="hl opt">}</span></pre>
250
251 <p>Calling the <tt>reset()</tt> method resets the <tt>QAbstractItemModel</tt> data model and assures that the associated widget
252 updates the <tt>QCompleter</tt> with a fresh list of auto completion words. Resetting the data model in this case is fine as
253 long as the data model is simple and the list short. The proper way would be finding out the actual insertion point and using
254 <tt>beginInsertRows()</tt> and <tt>endInsertRows()</tt> methods.</p>
255
256 <p>Querying data is much simpler thanks to the internal <tt>QMap</tt> container:</p>
257
258 <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>
259 <span class="hl opt">{</span>
260 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>
261 <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>
262 <span class="hl kwa">return</span> it<span class="hl opt">.</span><span class="hl kwd">value</span><span class="hl opt">();</span>
263 <span class="hl kwa">else</span>
264 <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>
265 <span class="hl opt">}</span></pre>
266
267 <p>We return an empty <tt>QExplicitlySharedDataPointer</tt> object if no data objects with the given name exists.</p>
268
269 <p>The <tt>data()</tt> method returns names of data objects for the <tt>QCompleter</tt> auto completion list of words:</p>
270
271 <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>
272 <span class="hl opt">{</span>
273 <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>
274 <span class="hl kwa">return</span> <span class="hl kwd">QVariant</span><span class="hl opt">();</span>
275
276 <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>
277 <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>
278
279 <span class="hl kwa">return</span> <span class="hl kwd">QVariant</span><span class="hl opt">();</span>
280 <span class="hl opt">}</span></pre>
281
282 <p>The <tt>createTabled()</tt> method creates the <tt>data</tt> table if it does not exist. This function could be improved to
283 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
284 is good for our application:</p>
285
286 <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>
287 <span class="hl opt">{</span>
288 QSqlQuery <span class="hl kwd">q</span><span class="hl opt">(</span>mDb<span class="hl opt">);</span>
289 <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>
290 QSqlError err <span class="hl opt">=</span> mDb<span class="hl opt">.</span><span class="hl kwd">lastError</span><span class="hl opt">();</span>
291 <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>
292 <span class="hl kwa">return false</span><span class="hl opt">;</span>
293 <span class="hl opt">}</span>
294
295 <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>
296 <span class="hl kwa">return true</span><span class="hl opt">;</span> <span class="hl slc">// We already have a table called 'data'</span>
297
298 <span class="hl slc">// Create the 'data' table</span>
299 <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>
300 QSqlError err <span class="hl opt">=</span> mDb<span class="hl opt">.</span><span class="hl kwd">lastError</span><span class="hl opt">();</span>
301 <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>
302 <span class="hl kwa">return false</span><span class="hl opt">;</span>
303 <span class="hl opt">}</span>
304
305 <span class="hl kwa">return true</span><span class="hl opt">;</span>
306 <span class="hl opt">}</span></pre>
307
308 <p>Finally, the <tt>loadData()</tt> method loads all the data records from the database to the memory:</p>
309
310 <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>
311 <span class="hl opt">{</span>
312 QSqlQuery <span class="hl kwd">q</span><span class="hl opt">(</span>mDb<span class="hl opt">);</span>
313 <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>
314 QSqlError err <span class="hl opt">=</span> mDb<span class="hl opt">.</span><span class="hl kwd">lastError</span><span class="hl opt">();</span>
315 <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>
316 <span class="hl kwa">return false</span><span class="hl opt">;</span>
317 <span class="hl opt">}</span>
318
319 <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>
320 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>
321 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>
322 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>
323 <span class="hl opt">}</span>
324
325 <span class="hl kwd">reset</span><span class="hl opt">();</span>
326
327 <span class="hl kwa">return true</span><span class="hl opt">;</span>
328 <span class="hl opt">}</span></pre>
329
330 <p>Resetting the <tt>QAbstractItemModel</tt> data model here is ok, becase before loading any data the model is supposed to be
331 empty.</p>
332
333 <p>Here is the complete <tt>module.cpp</tt> file:
334
335 <pre class="hl"><span class="hl com">/**</span>
336 <span class="hl com"> * &#64;file PswGen/Storage/module.cpp</span>
337 <span class="hl com"> */</span>
338
339 <span class="hl ppc">#include</span> <span class="hl pps">&quot;module.h&quot;</span><span class="hl ppc"></span>
340 <span class="hl ppc">#include</span> <span class="hl pps">&quot;version.h&quot;</span><span class="hl ppc"></span>
341
342 <span class="hl ppc">#include &lt;Common/Globals&gt;</span>
343 <span class="hl ppc">#include &lt;Common/iLogger&gt;</span>
344 <span class="hl ppc">#include &lt;Common/iRegistry&gt;</span>
345 <span class="hl ppc">#include &lt;Common/iApp&gt;</span>
346
347 <span class="hl ppc">#include &lt;QtCore&gt;</span>
348 <span class="hl ppc">#include &lt;QtSql/QtSql&gt;</span>
349
350 <span class="hl kwd">VER_EXPORT_VERSION_INFO</span><span class="hl opt">()</span>
351 <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>
352
353 <span class="hl kwa">using namespace</span> eVaf<span class="hl opt">;</span>
354 <span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">;</span>
355 <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>
356
357 Module<span class="hl opt">::</span><span class="hl kwd">Module</span><span class="hl opt">()</span>
358 <span class="hl opt">:</span> Plugins<span class="hl opt">::</span><span class="hl kwd">iPlugin</span><span class="hl opt">()</span>
359 <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>
360 <span class="hl opt">{</span>
361 <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>
362
363 mStorage <span class="hl opt">=</span> <span class="hl kwa">new</span> Internal<span class="hl opt">::</span>StorageImpl<span class="hl opt">;</span>
364
365 <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>
366 <span class="hl opt">}</span>
367
368 Module<span class="hl opt">::~</span><span class="hl kwd">Module</span><span class="hl opt">()</span>
369 <span class="hl opt">{</span>
370 <span class="hl kwa">delete</span> mStorage<span class="hl opt">;</span>
371
372 <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>
373 <span class="hl opt">}</span>
374
375 <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>
376 <span class="hl opt">{</span>
377 <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>args<span class="hl opt">);</span>
378
379 <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>
380 <span class="hl kwa">return false</span><span class="hl opt">;</span>
381
382 mReady <span class="hl opt">=</span> <span class="hl kwa">true</span><span class="hl opt">;</span>
383
384 <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>
385
386 <span class="hl kwa">return true</span><span class="hl opt">;</span>
387 <span class="hl opt">}</span>
388
389 <span class="hl kwb">void</span> Module<span class="hl opt">::</span><span class="hl kwd">done</span><span class="hl opt">()</span>
390 <span class="hl opt">{</span>
391 mReady <span class="hl opt">=</span> <span class="hl kwa">false</span><span class="hl opt">;</span>
392
393 mStorage<span class="hl opt">-&gt;</span><span class="hl kwd">done</span><span class="hl opt">();</span>
394
395 <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>
396 <span class="hl opt">}</span>
397
398 <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>
399
400 <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>
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>DbName <span class="hl opt">=</span> <span class="hl str">&quot;PswGen.sqlite&quot;</span><span class="hl opt">;</span>
403
404 StorageImpl<span class="hl opt">::</span><span class="hl kwd">StorageImpl</span><span class="hl opt">()</span>
405 <span class="hl opt">:</span> <span class="hl kwd">QAbstractListModel</span><span class="hl opt">()</span>
406 <span class="hl opt">{</span>
407 <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>
408
409 <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>
410 <span class="hl opt">}</span>
411
412 StorageImpl<span class="hl opt">::~</span><span class="hl kwd">StorageImpl</span><span class="hl opt">()</span>
413 <span class="hl opt">{</span>
414 <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>
415 <span class="hl opt">}</span>
416
417 <span class="hl kwb">bool</span> StorageImpl<span class="hl opt">::</span><span class="hl kwd">init</span><span class="hl opt">()</span>
418 <span class="hl opt">{</span>
419 <span class="hl slc">// Open the database</span>
420 <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>
421 <span class="hl slc">// No database connection yet</span>
422 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>
423 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>
424 <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>
425 QSqlError err <span class="hl opt">=</span> mDb<span class="hl opt">.</span><span class="hl kwd">lastError</span><span class="hl opt">();</span>
426 <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>
427 <span class="hl kwa">return false</span><span class="hl opt">;</span>
428 <span class="hl opt">}</span>
429 <span class="hl opt">}</span>
430 <span class="hl kwa">else</span> <span class="hl opt">{</span>
431 <span class="hl slc">// Database connection already exists</span>
432 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>
433 <span class="hl opt">}</span>
434
435 <span class="hl slc">// Create tables if necessary</span>
436 <span class="hl kwa">if</span> <span class="hl opt">(!</span><span class="hl kwd">createTables</span><span class="hl opt">())</span>
437 <span class="hl kwa">return false</span><span class="hl opt">;</span>
438
439 <span class="hl slc">// Load data</span>
440 <span class="hl kwa">if</span> <span class="hl opt">(!</span><span class="hl kwd">loadData</span><span class="hl opt">())</span>
441 <span class="hl kwa">return false</span><span class="hl opt">;</span>
442
443 <span class="hl slc">/// Register our interface</span>
444 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>
445
446 <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>
447
448 <span class="hl kwa">return true</span><span class="hl opt">;</span>
449 <span class="hl opt">}</span>
450
451 <span class="hl kwb">void</span> StorageImpl<span class="hl opt">::</span><span class="hl kwd">done</span><span class="hl opt">()</span>
452 <span class="hl opt">{</span>
453 mData<span class="hl opt">.</span><span class="hl kwd">clear</span><span class="hl opt">();</span>
454 <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>
455 <span class="hl opt">}</span>
456
457 <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>
458 <span class="hl opt">{</span>
459 <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>
460 <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>
461
462 <span class="hl slc">// Is it an update or a new data record?</span>
463 <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>
464 <span class="hl slc">// This is an update</span>
465 <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>
466 QSqlQuery <span class="hl kwd">q</span><span class="hl opt">(</span>mDb<span class="hl opt">);</span>
467 <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>
468 <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>
469 QSqlError err <span class="hl opt">=</span> mDb<span class="hl opt">.</span><span class="hl kwd">lastError</span><span class="hl opt">();</span>
470 <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>
471 <span class="hl kwa">return false</span><span class="hl opt">;</span>
472 <span class="hl opt">}</span>
473 <span class="hl opt">}</span>
474 <span class="hl opt">}</span>
475 <span class="hl kwa">else</span> <span class="hl opt">{</span>
476 <span class="hl slc">// Store to the database</span>
477 QSqlQuery <span class="hl kwd">q</span><span class="hl opt">(</span>mDb<span class="hl opt">);</span>
478 <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>
479 <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>
480 <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>
481 QSqlError err <span class="hl opt">=</span> mDb<span class="hl opt">.</span><span class="hl kwd">lastError</span><span class="hl opt">();</span>
482 <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>
483 <span class="hl kwa">return false</span><span class="hl opt">;</span>
484 <span class="hl opt">}</span>
485
486 <span class="hl slc">// Store also into the local hash</span>
487 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>
488
489 <span class="hl slc">// Reset the model</span>
490 <span class="hl kwd">reset</span><span class="hl opt">();</span>
491 <span class="hl opt">}</span>
492
493 data<span class="hl opt">-&gt;</span><span class="hl kwd">reset</span><span class="hl opt">();</span>
494
495 <span class="hl kwa">return true</span><span class="hl opt">;</span>
496 <span class="hl opt">}</span>
497
498 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>
499 <span class="hl opt">{</span>
500 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>
501 <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>
502 <span class="hl kwa">return</span> it<span class="hl opt">.</span><span class="hl kwd">value</span><span class="hl opt">();</span>
503 <span class="hl kwa">else</span>
504 <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>
505 <span class="hl opt">}</span>
506
507 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>
508 <span class="hl opt">{</span>
509 <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>
510 <span class="hl kwa">return</span> <span class="hl kwd">QVariant</span><span class="hl opt">();</span>
511
512 <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>
513 <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>
514
515 <span class="hl kwa">return</span> <span class="hl kwd">QVariant</span><span class="hl opt">();</span>
516 <span class="hl opt">}</span>
517
518 <span class="hl kwb">bool</span> StorageImpl<span class="hl opt">::</span><span class="hl kwd">createTables</span><span class="hl opt">()</span>
519 <span class="hl opt">{</span>
520 QSqlQuery <span class="hl kwd">q</span><span class="hl opt">(</span>mDb<span class="hl opt">);</span>
521 <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>
522 QSqlError err <span class="hl opt">=</span> mDb<span class="hl opt">.</span><span class="hl kwd">lastError</span><span class="hl opt">();</span>
523 <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>
524 <span class="hl kwa">return false</span><span class="hl opt">;</span>
525 <span class="hl opt">}</span>
526
527 <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>
528 <span class="hl kwa">return true</span><span class="hl opt">;</span> <span class="hl slc">// We already have a table called 'data'</span>
529
530 <span class="hl slc">// Create the 'data' table</span>
531 <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>
532 QSqlError err <span class="hl opt">=</span> mDb<span class="hl opt">.</span><span class="hl kwd">lastError</span><span class="hl opt">();</span>
533 <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>
534 <span class="hl kwa">return false</span><span class="hl opt">;</span>
535 <span class="hl opt">}</span>
536
537 <span class="hl kwa">return true</span><span class="hl opt">;</span>
538 <span class="hl opt">}</span>
539
540 <span class="hl kwb">bool</span> StorageImpl<span class="hl opt">::</span><span class="hl kwd">loadData</span><span class="hl opt">()</span>
541 <span class="hl opt">{</span>
542 QSqlQuery <span class="hl kwd">q</span><span class="hl opt">(</span>mDb<span class="hl opt">);</span>
543 <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>
544 QSqlError err <span class="hl opt">=</span> mDb<span class="hl opt">.</span><span class="hl kwd">lastError</span><span class="hl opt">();</span>
545 <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>
546 <span class="hl kwa">return false</span><span class="hl opt">;</span>
547 <span class="hl opt">}</span>
548
549 <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>
550 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>
551 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>
552 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>
553 <span class="hl opt">}</span>
554
555 <span class="hl kwd">reset</span><span class="hl opt">();</span>
556
557 <span class="hl kwa">return true</span><span class="hl opt">;</span>
558 <span class="hl opt">}</span></pre>
559
560 <p>Next -- <a href="pswgen08.html">Building Storage Module</a>.</p>
561
562 </body>
563 </html>