--- /dev/null
+/* Style definition file generated by highlight 3.3, http://www.andre-simon.de/ */
+
+/* Highlighting theme: Kwrite Editor */
+
+body.hl { background-color:#e0eaee; }
+pre.hl { color:#000000; background-color:#e0eaee; font-size:10pt; font-family:'Courier New';}
+.hl.num { color:#b07e00; }
+.hl.esc { color:#ff00ff; }
+.hl.str { color:#bf0303; }
+.hl.pps { color:#818100; }
+.hl.slc { color:#838183; font-style:italic; }
+.hl.com { color:#838183; font-style:italic; }
+.hl.ppc { color:#008200; }
+.hl.opt { color:#000000; }
+.hl.lin { color:#555555; }
+.hl.kwa { color:#000000; font-weight:bold; }
+.hl.kwb { color:#0057ae; }
+.hl.kwc { color:#000000; font-weight:bold; }
+.hl.kwd { color:#010181; }
+
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang="et" xmlns="http://www.w3.org/1999/xhtml" xml:lang="et">
+
+ <head>
+ <meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />
+ <title>eVaf Tutorial - 02 - Preparations</title>
+ <meta name="Author" content="Enar Väikene" />
+ <meta name="description" content="eVaf Tutorial" />
+ <meta name="keywords" content="evaf c++ application development framework tutorial password generator" />
+ <link rel="StyleSheet" href="evaf.css" type="text/css" media="all" />
+ </head>
+
+ <body>
+
+ <h1>eVaf Tutorial</h1>
+
+ <h2>02 - Preparations</h2>
+
+ <p>In the next section <a href="pswgen03.html">03 - Generator Module</a> we write the Generator module.</p>
+
+ </body>
+
+</html>
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang="et" xmlns="http://www.w3.org/1999/xhtml" xml:lang="et">
+
+ <head>
+ <meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />
+ <title>eVaf Tutorial - 03 - Generator Module</title>
+ <meta name="Author" content="Enar Väikene" />
+ <meta name="description" content="eVaf Tutorial" />
+ <meta name="keywords" content="evaf c++ application development framework tutorial password generator" />
+ <link rel="StyleSheet" href="evaf.css" type="text/css" media="all" />
+ <link rel="StyleSheet" href="highlight.css" type="text/css" media="all" />
+ </head>
+
+ <body>
+
+ <h1>eVaf Tutorial</h1>
+
+ <h2>03 - Generator Module</h2>
+
+ <p>In this section we write the Generator module. According to the specification, the Generator module has to
+ generate strong passwords in such a way that by feeding the module with the same input data we always get the
+ same password.</p>
+
+ <h3>iGenerator interface</h3>
+
+ <p>We start by defining the interface for the module. For this create the file <tt>igenerator.h</tt> in the
+ <tt>src/apps/pswGen/Generator</tt> directory:</p>
+
+ <pre class="hl"><span class="hl com">/**</span>
+<span class="hl com"> * @file src/apps/PswGen/Generator/igenerator.h</span>
+<span class="hl com"> */</span>
+<span class="hl ppc">#ifndef __PSWGEN_GENERATOR_IGENERATOR_H</span>
+<span class="hl ppc"># define __PSWGEN_GENERATOR_IGENERATOR_H</span>
+
+<span class="hl ppc">#endif</span> <span class="hl slc">// igenerator.h</span><span class="hl ppc"></span></pre>
+
+ <p>The interface class needs to be derived from <tt>QObject</tt> and we also need <tt>QString</tt> for input
+ data and generated passwords:</p>
+
+ <pre class="hl"><span class="hl ppc">#include <QObject></span>
+<span class="hl ppc">#include <QString></span></pre>
+
+ <p>To avoid potential name collisions with other existing or future modules, we use the <tt>eVaf::PswGen</tt>
+ namespace for this application:</p>
+
+ <pre class="hl"><span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span>
+<span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span>
+
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span>
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span></pre>
+
+ <p>We call the interface class <tt>iGenerator</tt>:
+
+ <pre class="hl"><span class="hl kwc">class</span> iGenerator <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject
+<span class="hl opt">{</span>
+ Q_OBJECT
+<span class="hl kwc">public</span><span class="hl opt">:</span>
+<span class="hl opt">};</span></pre>
+
+ <p>All the interface classes need a default constructor and an empty virtual destructor. Do not perform any actions
+ in these constructors and destructors. Instead, leave it up to the class that implements the interface.</p>
+ <pre class="hl"><span class="hl slc">/// Interface constructor</span>
+<span class="hl kwd">iGenerator</span><span class="hl opt">() :</span> <span class="hl kwd">QObject</span><span class="hl opt">() {}</span>
+
+<span class="hl slc">/// Empty virtual destructor</span>
+<span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">iGenerator</span><span class="hl opt">() {}</span></pre>
+
+ <p>Now we add the functionality to the interface and according to the specification we need two functions -- one that
+ generates passwords and another that returns the maximum length of the password:</p>
+
+ <pre class="hl"><span class="hl kwc">virtual</span> QString <span class="hl kwd">generatePassword</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&</span> masterPassword<span class="hl opt">,</span> <span class="hl kwb">int</span> length<span class="hl opt">,</span> uint flags <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">)</span> <span class="hl kwb">const</span> <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">;</span>
+
+<span class="hl kwc">virtual</span> <span class="hl kwb">int</span> <span class="hl kwd">maxLength</span><span class="hl opt">()</span> <span class="hl kwb">const</span> <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">;</span></pre>
+
+ <p>I am training myself to use the style of writing declarations like <tt>"QString const &"</tt>, which refers to a non-mutable <tt>QString</tt> object similar to <tt>"int maxLength() const"</tt>, which is a function that does not modify the object's data members. Feel free to use the traditional way of writing <tt>"const QString &"</tt> if this looks weird to you.</p>
+
+ <p>The <tt>iGenerator</tt> interface needs to be visible for other modules and marked for export. We do this by creating the <tt>src/apps/PswGen/Generator/lib.h file, which defines the <tt>PSWGEN_GENERATOR_EXPORT</tt> macro:</p>
+ <pre class="hl"><span class="hl com">/**</span>
+<span class="hl com"> * @file src/apps/PswGen/Generator/lib.h</span>
+<span class="hl com"> */</span>
+<span class="hl ppc">#ifndef __PSWGEN_GENERATOR_LIB_H</span>
+<span class="hl ppc"># define __PSWGEN_GENERATOR_LIB_H</span>
+
+<span class="hl ppc">#include <QtCore/qglobal.h></span>
+
+<span class="hl ppc">#if defined(PSWGEN_GENERATOR_LIBRARY)</span>
+<span class="hl ppc"># define PSWGEN_GENERATOR_EXPORT Q_DECL_EXPORT</span>
+<span class="hl ppc">#else</span>
+<span class="hl ppc"># define PSWGEN_GENERATOR_EXPORT Q_DECL_IMPORT</span>
+<span class="hl ppc">#endif</span>
+<span class="hl ppc">#endif</span> <span class="hl slc">// libgen.h</span><span class="hl ppc"></span></pre>
+
+ <p>Then we include this new header file in our interface header file and modify the <tt>iGenerator</tt> class definition by adding
+ the <tt>PSWGEN_GENERATOR_EXPORT</tt> macro to it:</p>
+ <pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">"lib.h"</span><span class="hl ppc"></span>
+
+/// ...
+
+<span class="hl kwc">class</span> PSWGEN_GENERATOR_EXPORT iGenerator <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject</pre>
+
+ <p>This is pretty much all we need to add to the <tt>iGenerator</tt> interface and here is the final file:</p>
+
+<pre class="hl"><span class="hl com">/**</span>
+<span class="hl com"> * @file src/apps/PswGen/Generator/igenerator.h</span>
+<span class="hl com"> */</span>
+
+<span class="hl ppc">#ifndef __PSWGEN_GENERATOR_IGENERATOR_H</span>
+<span class="hl ppc"># define __PSWGEN_GENERATOR_IGENERATOR_H</span>
+
+<span class="hl ppc">#include</span> <span class="hl pps">"lib.h"</span><span class="hl ppc"></span>
+
+<span class="hl ppc">#include <QObject></span>
+<span class="hl ppc">#include <QString></span>
+
+<span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span>
+<span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span>
+
+<span class="hl com">/// Password generator interface.</span>
+<span class="hl kwc">class</span> PSWGEN_GENERATOR_EXPORT iGenerator <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject
+<span class="hl opt">{</span>
+ Q_OBJECT
+
+<span class="hl kwc">public</span><span class="hl opt">:</span>
+
+ <span class="hl slc">/// Interface constructor</span>
+ <span class="hl kwd">iGenerator</span><span class="hl opt">() :</span> <span class="hl kwd">QObject</span><span class="hl opt">() {}</span>
+
+ <span class="hl slc">/// Empty virtual destructor</span>
+ <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">iGenerator</span><span class="hl opt">() {}</span>
+
+ <span class="hl com">/// Generates a strong password</span>
+ <span class="hl kwc">virtual</span> QString <span class="hl kwd">generatePassword</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&</span> masterPassword<span class="hl opt">,</span> <span class="hl kwb">int</span> length<span class="hl opt">,</span> uint flags <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">)</span> <span class="hl kwb">const</span> <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">;</span>
+
+ <span class="hl com">/// Returns the maximum length of generated passwords</span>
+ <span class="hl kwc">virtual</span> <span class="hl kwb">int</span> <span class="hl kwd">maxLength</span><span class="hl opt">()</span> <span class="hl kwb">const</span> <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">;</span>
+
+<span class="hl opt">};</span>
+
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span>
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span>
+
+<span class="hl ppc">#endif</span> <span class="hl slc">// igenerator.h</span><span class="hl ppc"></span>
+</pre>
+
+ <p>As a final touch, we create a file called <tt>iGenerator</tt> with the following content:</p>
+<pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">"igenerator.h"</span><span class="hl ppc"></span></pre>
+
+ <p>With this file in place other modules can use <tt>#include "Generator/iGenerator"</tt> instead of <tt>#include "Generator/igenerator.h"</tt> similar to other eVaf and Qt include files.</p>
+
+ <h3>Generator module</h3>
+
+ <p>Now we write the Generator module itself. The module class has to be derived from the <tt>Plugins::iPlugin</tt> interface class
+ with or without the <tt>Plugins::iPluginFactory</tt> factory class.</p>
+
+ <p>The <tt>Plugins::iPluginFactory</tt> factory class should be used when more than one plugins are implemented by the same
+ module. The factory class takes care of creating individual plugins whenever they are instantiated. This module implements only
+ one plugin and we opt to the implementation without the factory class.</p>
+
+ <p>Create the <tt>module.h</tt> header file in the <tt>src/apps/PswGen/Generator</tt> directory:</p>
+
+ <pre class="hl"><span class="hl com">/**</span>
+<span class="hl com"> * @file src/apps/PswGen/Generator/module.h</span>
+<span class="hl com"> */</span>
+<span class="hl ppc">#ifndef __PSWGEN_GENERATOR_MODULE_H</span>
+<span class="hl ppc"># define __PSWGEN_GENERATOR_MODULE_H</span>
+
+<span class="hl ppc">#endif</span> <span class="hl slc">// module.h</span><span class="hl ppc"></span></pre>
+
+ <p>As this is a simple module, we define all our class in this single header file. This includes the implementation
+ of the <tt>iGenerator</tt> interface and also the plugin itself. Se we need to include header files for the
+ <tt>iGenerator</tt> and <tt>iPlugin</tt> interfaces:</p>
+
+<pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">"igenerator.h"</span><span class="hl ppc"></span>
+<span class="hl ppc">#include <Plugins/iPlugin></span></pre>
+
+ <p>We are going to put every public class in this module into the <tt>eVaf::PswGen::Generator</tt> namespace and private
+ classes into the <tt>eVaf::PswGen::Generator::Private</tt> namespace:</p>
+
+<pre class="hl"><span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span>
+<span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span>
+
+<span class="hl slc">/// Module that generates strong passwords using cryptographic methods</span>
+<span class="hl kwa">namespace</span> Generator <span class="hl opt">{</span>
+
+<span class="hl slc">/// Internal implementation of the Generator module</span>
+<span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span>
+
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span>
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator</span>
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span>
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span></pre>
+
+ <p>We call the class that implements the module simply <tt>Module</tt>. This is a public class and goes into the
+ <tt>eVaf::PswGen::Generator</tt> namespace</tt>. We however, do not need to export it as we did with the <tt>iGenerator</tt>
+ interface class, as this will be done by Qt.</p>
+
+<pre class="hl"><span class="hl kwc">class</span> Module <span class="hl opt">:</span> <span class="hl kwc">public</span> Plugins<span class="hl opt">::</span>iPlugin
+<span class="hl opt">{</span>
+ Q_OBJECT
+
+<span class="hl kwc">public</span><span class="hl opt">:</span>
+
+ <span class="hl kwd">Module</span><span class="hl opt">();</span>
+
+ <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">Module</span><span class="hl opt">();</span>
+
+}</span></pre>
+
+ <p>The <tt>iPlugin</tt> interface has three abstract methods that we need to implement in our class -- <tt>init()</tt>,
+ <tt>done()</tt> and <tt>isReady()</tt>. Since this simple module is always ready, we can return <tt>true</tt> in the
+ <tt>isReady()</tt> function. More complex modules can use a private <tt>mReady</tt> variable, which they set to <tt>true</tt>
+ once all the initialization is done.</tt>
+
+<pre class="hl"><span class="hl kwc">virtual</span> <span class="hl kwb">bool</span> <span class="hl kwd">init</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> args<span class="hl opt">);</span>
+
+<span class="hl kwc">virtual</span> <span class="hl kwb">void</span> <span class="hl kwd">done</span><span class="hl opt">();</span>
+
+<span class="hl kwc">virtual</span> <span class="hl kwb">bool</span> <span class="hl kwd">isReady</span><span class="hl opt">()</span> <span class="hl kwb">const</span> <span class="hl opt">{</span> <span class="hl kwa">return true</span><span class="hl opt">; }</pre>
+
+ <p>We need the <tt>iGenerator</tt> interface object in this module and add it to the private members section:</tt>
+
+<pre class="hl"><span class="hl kwc">private</span><span class="hl opt">:</span> <span class="hl slc">// Members</span>
+
+ <span class="hl slc">/// iGenerator interface instance</span>
+ Internal<span class="hl opt">::</span>GeneratorImpl <span class="hl opt">*</span> mGenerator<span class="hl opt">;</span></pre>
+
+ <p>As the <tt>Internal::GeneratorImpl</tt> class is not declared yet, we need to add this forward declaration before the
+ <tt>Module</tt> class:</p>
+
+<pre class="hl"><span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span>
+ <span class="hl kwc">class</span> GeneratorImpl<span class="hl opt">;</span>
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span></pre>
+
+ <p>Then we can move forward and implement the <tt>iGenerator</tt> interface, which we already happened to call
+ <tt>GeneratorImpl</tt>. This class goes into the <tt>eVaf::PswGen::Generator::Internal</tt> namespace:</p>
+
+<pre class="hl"><span class="hl kwc">class</span> GeneratorImpl <span class="hl opt">:</span> <span class="hl kwc">public</span> iGenerator
+<span class="hl opt">{</span>
+ Q_OBJECT
+
+<span class="hl kwc">public</span><span class="hl opt">:</span>
+
+ <span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span>
+
+ <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span>
+
+ <span class="hl kwc">virtual</span> QString <span class="hl kwd">generatePassword</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&</span> masterPassword<span class="hl opt">,</span> <span class="hl kwb">int</span> length<span class="hl opt">,</span> uint flags <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">)</span> <span class="hl kwb">const</span><span class="hl opt">;</span>
+
+ <span class="hl kwc">virtual</span> <span class="hl kwb">int</span> <span class="hl kwd">maxLength</span><span class="hl opt">()</span> <span class="hl kwb">const;</span>
+<span class="hl opt">};</span></pre>
+
+ <p>Here is the final <tt>module.h</tt> file:</p>
+
+<pre class="hl"><span class="hl com">/**</span>
+<span class="hl com"> * @file src/apps/PswGen/Generator/module.h</span>
+<span class="hl com"> */</span>
+
+<span class="hl ppc">#ifndef __PSWGEN_GENERATOR_MODULE_H</span>
+<span class="hl ppc"># define __PSWGEN_GENERATOR_MODULE_H</span>
+
+<span class="hl ppc">#include</span> <span class="hl pps">"igenerator.h"</span><span class="hl ppc"></span>
+
+<span class="hl ppc">#include <Plugins/iPlugin></span>
+
+<span class="hl ppc">#include <QObject></span>
+<span class="hl ppc">#include <QString></span>
+
+<span class="hl kwa">namespace</span> eVaf <span class="hl opt">{</span>
+<span class="hl kwa">namespace</span> PswGen <span class="hl opt">{</span>
+
+<span class="hl slc">/// Module that generates strong passwords using cryptographic methods</span>
+<span class="hl kwa">namespace</span> Generator <span class="hl opt">{</span>
+
+<span class="hl slc">/// Internal implementation of the Generator module</span>
+<span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span>
+ <span class="hl kwc">class</span> GeneratorImpl<span class="hl opt">;</span>
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span>
+
+<span class="hl com">/// Plugins/iPlugin interface implementation.</span>
+<span class="hl kwc">class</span> Module <span class="hl opt">:</span> <span class="hl kwc">public</span> Plugins<span class="hl opt">::</span>iPlugin
+<span class="hl opt">{</span>
+ Q_OBJECT
+
+<span class="hl kwc">public</span><span class="hl opt">:</span>
+
+ <span class="hl kwd">Module</span><span class="hl opt">();</span>
+
+ <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">Module</span><span class="hl opt">();</span>
+
+ <span class="hl kwc">virtual</span> <span class="hl kwb">bool</span> <span class="hl kwd">init</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> args<span class="hl opt">);</span>
+
+ <span class="hl kwc">virtual</span> <span class="hl kwb">void</span> <span class="hl kwd">done</span><span class="hl opt">();</span>
+
+ <span class="hl kwc">virtual</span> <span class="hl kwb">bool</span> <span class="hl kwd">isReady</span><span class="hl opt">()</span> <span class="hl kwb">const</span> <span class="hl opt">{</span> <span class="hl kwa">return true</span><span class="hl opt">; }</span>
+
+
+<span class="hl kwc">private</span><span class="hl opt">:</span> <span class="hl slc">// Members</span>
+
+ <span class="hl slc">/// iGenerator interface instance</span>
+ Internal<span class="hl opt">::</span>GeneratorImpl <span class="hl opt">*</span> mGenerator<span class="hl opt">;</span>
+
+<span class="hl opt">};</span>
+
+<span class="hl kwa">namespace</span> Internal <span class="hl opt">{</span>
+
+<span class="hl com"> /// iGenerator interface implementation.</span>
+<span class="hl kwc">class</span> GeneratorImpl <span class="hl opt">:</span> <span class="hl kwc">public</span> iGenerator
+<span class="hl opt">{</span>
+ Q_OBJECT
+
+<span class="hl kwc">public</span><span class="hl opt">:</span>
+
+ <span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span>
+
+ <span class="hl kwc">virtual</span> <span class="hl opt">~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">();</span>
+
+ <span class="hl kwc">virtual</span> QString <span class="hl kwd">generatePassword</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&</span> masterPassword<span class="hl opt">,</span> <span class="hl kwb">int</span> length<span class="hl opt">,</span> uint flags <span class="hl opt">=</span> <span class="hl num">0</span><span class="hl opt">)</span> <span class="hl kwb">const</span><span class="hl opt">;</span>
+
+ <span class="hl kwc">virtual</span> <span class="hl kwb">int</span> <span class="hl kwd">maxLength</span><span class="hl opt">()</span> <span class="hl kwb">const;</span>
+
+<span class="hl opt">};</span>
+
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator::Internal</span>
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen::Generator</span>
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf::PswGen</span>
+<span class="hl opt">}</span> <span class="hl slc">// namespace eVaf</span>
+
+<span class="hl ppc">#endif</span> <span class="hl slc">// module.h</span><span class="hl ppc"></span></pre>
+
+ <p>Continue implementing the <a href="pswgen04.html">Generator Module</a>.</p>
+
+ </body>
+
+</html>
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang="et" xmlns="http://www.w3.org/1999/xhtml" xml:lang="et">
+
+ <head>
+ <meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />
+ <title>eVaf Tutorial - 04 - Generator Module</title>
+ <meta name="Author" content="Enar Väikene" />
+ <meta name="description" content="eVaf Tutorial" />
+ <meta name="keywords" content="evaf c++ application development framework tutorial password generator" />
+ <link rel="StyleSheet" href="evaf.css" type="text/css" media="all" />
+ <link rel="StyleSheet" href="highlight.css" type="text/css" media="all" />
+ </head>
+
+ <body>
+
+ <h1>eVaf Tutorial</h1>
+
+ <h2>04 - Generator Module</h2>
+
+ <p>Now we are going to implement all the classes declared in the <tt>module.h</tt>. Create the <tt>module.cpp</tt> file
+ in the <tt>src/apps/PswGen/Generator</tt> directory. We obviously include the <tt>module.h</tt> header file, but also
+ the <tt>QtCore</tt> header file for any non-GUI Qt classes.</p>
+
+<pre class="hl"><span class="hl com">/**</span>
+<span class="hl com"> * @file src/apps/PswGen/Generator/module.cpp</span>
+<span class="hl com"> */</span>
+
+<span class="hl ppc">#include</span> <span class="hl pps">"module.h"</span><span class="hl ppc"></span>
+
+<span class="hl ppc">#include <QtCore></span></pre>
+
+ <p>All the eVaf modules need to include version information. This is common for all the modules and we can simply
+ copy existing version info files from another eVaf module:</p>
+
+ <pre>evaf/src/apps/PswGen/Generator $ <code>cp ../../../plugins/SdiWindow/version.{h,rc} .</code></pre>
+
+ <p>The <tt>version.h</tt> file contains version information for the module. The <tt>version.rc</tt> is for Windows
+ builds only and embeds the same version information into the dll or exe file. Modify the copied <tt>version.h</tt>
+ file for our new module. The <tt>version.rc</tt> file uses the values from the <tt>version.h</tt> and does not
+ need to be touched.</p>
+
+<pre class="hl"><span class="hl com">/**</span>
+<span class="hl com"> * @file src/apps/PswGen/Generator/version.h</span>
+<span class="hl com"> */</span>
+<span class="hl ppc">#ifndef __PSWGEN_GENERATOR_VERSION_H</span>
+<span class="hl ppc">#define __PSWGEN_GENERATOR_VERSION_H</span>
+
+<span class="hl ppc">#include <version_rc.h></span>
+
+<span class="hl com">/**</span>
+<span class="hl com"> * Module/library version number in the form major,minor,release,build</span>
+<span class="hl com"> */</span>
+<span class="hl ppc">#define VER_FILE_VERSION 0,1,1,1</span>
+
+<span class="hl com">/**</span>
+<span class="hl com"> * Module/library version number in the string format (shall end with \0)</span>
+<span class="hl com"> */</span>
+<span class="hl ppc">#define VER_FILE_VERSION_STR</span> <span class="hl pps">"0.1.1.1\0"</span><span class="hl ppc"></span>
+
+<span class="hl com">/**</span>
+<span class="hl com"> * Module/library name (shall end with \0)</span>
+<span class="hl com"> */</span>
+<span class="hl ppc">#define VER_MODULE_NAME_STR</span> <span class="hl pps">"PswGen\0"</span><span class="hl ppc"></span>
+
+<span class="hl com">/**</span>
+<span class="hl com"> * Module type (see version_rc.h for all the types)</span>
+<span class="hl com"> */</span>
+<span class="hl ppc">#define VER_MODULE_TYPE MT_GENERIC</span>
+
+<span class="hl com">/**</span>
+<span class="hl com"> * Module type in the string format (see version_rc for all the types)</span>
+<span class="hl com"> */</span>
+<span class="hl ppc">#define VER_MODULE_TYPE_STR MT_GENERIC</span>
+
+<span class="hl com">/**</span>
+<span class="hl com"> * Original file name for windows (shall end with \0)</span>
+<span class="hl com"> */</span>
+<span class="hl ppc">#define VER_ORIGINAL_FILE_NAME_STR</span> <span class="hl pps">"PswGen.dll\0"</span><span class="hl ppc"></span>
+
+<span class="hl com">/**</span>
+<span class="hl com"> * Description of the module/library (shall end with \0)</span>
+<span class="hl com"> */</span>
+<span class="hl ppc">#define VER_FILE_DESCRIPTION_STR</span> <span class="hl pps">"Module that generates strong passwords using MD5 hashes.\0"</span><span class="hl ppc"></span>
+
+<span class="hl ppc">#endif</span> <span class="hl slc">// version.h</span><span class="hl ppc"></span></pre>
+
+ <p>Then include the version info file in the <tt>module.cpp</tt> file and use the <tt>VER_EXPORT_VERSION_INFO()</tt> macro
+ to export version information from the module. This macro defines a public function that all the eVaf modules export and
+ is used to collect version information from them. In your modules you only need to modify the <tt>version.h</tt> file and then
+ use the <tt>VER_EXPORT_VERSION_INFO()</tt> macro once somewhere in your code.</p>
+
+<pre class="hl"><span class="hl ppc">#include</span> <span class="hl pps">"version.h"</span><span class="hl ppc"></span>
+
+<span class="hl kwd">VER_EXPORT_VERSION_INFO</span><span class="hl opt">()</span></pre>
+
+ <p>We make our life easier with several <tt>using namespace</tt> keywords:</p>
+
+<pre class="hl"><span class="hl kwa">using namespace</span> eVaf<span class="hl opt">;</span>
+<span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">;</span>
+<span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>Generator<span class="hl opt">;</span></pre>
+
+ <p>The Module class needs to instantiate the <tt>iGenerator</tt> interface in the constructor. We also need to set
+ the QObject's name property to the name of the plugin by combining the name of the module with the name of the class.
+ While the application would work without the name property, it makes our life much easier if the name property is set.</p>
+
+ <p>Finally, we output an info message telling that the object was created. Every eVaf module and class is expected to
+ output info messages when they are created, destroyed, initialized or destroyed.</p>
+
+<pre class="hl">Module<span class="hl opt">::</span><span class="hl kwd">Module</span><span class="hl opt">()</span>
+ <span class="hl opt">:</span> Plugins<span class="hl opt">::</span><span class="hl kwd">iPlugin</span><span class="hl opt">()</span>
+<span class="hl opt">{</span>
+ <span class="hl kwd">setObjectName</span><span class="hl opt">(</span><span class="hl kwd">QString</span><span class="hl opt">(</span><span class="hl str">"%1.%2"</span><span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>VER_MODULE_NAME_STR<span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>__FUNCTION__<span class="hl opt">));</span>
+
+ mGenerator <span class="hl opt">=</span> <span class="hl kwa">new</span> Internal<span class="hl opt">::</span>GeneratorImpl<span class="hl opt">;</span>
+
+ <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s created"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span>
+<span class="hl opt">}</span></pre>
+
+ <p>The <tt>EVAF_INFO</tt> macro comes from the <tt>Common/iLogger</tt> header file ane we need to include it:</p>
+
+<pre class="hl"><span class="hl ppc">#include <Common/iLogger></span></pre>
+
+ <p>The destructor should delete the <tt>iGenerator</tt> interface object, which we created in the constructor. The common
+ rule is that any resources allocated in the constructor shall be released in the destructor, preferrably in the opposite
+ order, ie. the first resource allocated in the constructor is released last in the destructor.</tt>
+
+<pre class="hl">Module<span class="hl opt">::~</span><span class="hl kwd">Module</span><span class="hl opt">()</span>
+<span class="hl opt">{</span>
+ <span class="hl kwa">delete</span> mGenerator<span class="hl opt">;</span>
+
+ <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s destroyed"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span>
+<span class="hl opt">}</span></pre>
+
+ <p>We also need to implement <tt>init()</tt> and <tt>done()</tt> functions, which are used to initialize and finalize modules.
+ They are similar to the constructor and destructor with two major differences:</p>
+ <ol>
+ <li>The <tt>init()</tt> function can fail and return <tt>false</tt> to indicate a failure. eVaf does not use exceptions and
+ this is the only way for a module to fail without terminating the whole application. A failed module will be disabled
+ and the rest of the application can still run if it can.</li>
+ <li>eVaf modules are loaded in two steps. At first, all the modules are created, which means that all the objects
+ are constructed. Only then will eVaf call <tt>init()</tt> functions meaning that when the <tt>init()</tt> function is
+ called, all the modules are already loaded and instantiated. Interfaces and resources from other modules that might be not
+ available when the object is created, are available when the <tt>init()</tt> function is called.</li>
+ </ol>
+
+ <p>The rule for <tt>init()</tt> and <tt>done()</tt> functions is the same than for constructors and destructors -- any resource
+ allocated in the <tt>init()</tt> function shall be released in the <tt>done()</tt> function and preferrably in the opposite
+ order.</p>
+
+ <p>This simple module needs no extra resources to be allocated and our <tt>init()</tt> and <tt>done()</tt> functions can be
+ the following:</p>
+
+<pre class="hl"><span class="hl kwb">bool</span> Module<span class="hl opt">::</span><span class="hl kwd">init</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> args<span class="hl opt">)</span>
+<span class="hl opt">{</span>
+ <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>args<span class="hl opt">);</span>
+
+ <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s initialized"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span>
+
+ <span class="hl kwa">return true</span><span class="hl opt">;</span>
+<span class="hl opt">}</span>
+
+<span class="hl kwb">void</span> Module<span class="hl opt">::</span><span class="hl kwd">done</span><span class="hl opt">()</span>
+<span class="hl opt">{</span>
+ <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s finalized"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span>
+<span class="hl opt">}</span></pre>
+
+ <p>We continue by implementing the <tt>iGenerator</tt> interface. There are no resources to be allocated in the constructor
+ and we just set the QObject's name property and output the info message.</p>
+
+ <p>We also register the <tt>iGenerator</tt> interface in the global registry so that other modules can query for it and
+ use our interface. This is done by using the <tt>Common::iRegistry</tt> interface, which we need to include:</p>
+
+<pre class="hl"><span class="hl ppc">#include <Common/iRegistry></span></pre>
+
+ <p>The <tt>GeneratorImpl</tt> class was declared in the <tt>eVaf::PswGen::Generator::Internal</tt> namespace, so we need
+ another <tt>using namespace</tt> keyword before the implementation of the class:</p>
+
+<pre class="hl"><span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>Generator<span class="hl opt">::</span>Internal<span class="hl opt">;</span>
+
+GeneratorImpl<span class="hl opt">::</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">()</span>
+ <span class="hl opt">:</span> <span class="hl kwd">iGenerator</span><span class="hl opt">()</span>
+<span class="hl opt">{</span>
+ <span class="hl kwd">setObjectName</span><span class="hl opt">(</span><span class="hl kwd">QString</span><span class="hl opt">(</span><span class="hl str">"%1.iGenerator"</span><span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>VER_MODULE_NAME_STR<span class="hl opt">));</span>
+
+ Common<span class="hl opt">::</span>iRegistry<span class="hl opt">::</span><span class="hl kwd">instance</span><span class="hl opt">()-></span><span class="hl kwd">registerInterface</span><span class="hl opt">(</span><span class="hl str">"iGenerator"</span><span class="hl opt">,</span> <span class="hl kwa">this</span><span class="hl opt">);</span>
+
+ <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s created"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span>
+<span class="hl opt">}</span>
+
+GeneratorImpl<span class="hl opt">::~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">()</span>
+<span class="hl opt">{</span>
+ <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s destroyed"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span>
+<span class="hl opt">}</span></pre>
+
+ <p>Finally, we write the <tt>generatePassword</tt> function that does the actual job of the module.</p>
+
+ <p>We use the MD5 cryptographic hash function to calculate a hash value over the <tt>name</tt> and <tt>masterPassword</tt> values.
+ The result, which is a binary blob, needs to be convert into something that can be used as a password and we use base 64 encoding
+ for this and cut the result to the requested length:</p>
+
+<pre class="hl">QString GeneratorImpl<span class="hl opt">::</span><span class="hl kwd">generatePassword</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&</span> masterPassword<span class="hl opt">,</span> <span class="hl kwb">int</span> length<span class="hl opt">,</span> uint flags<span class="hl opt">)</span> <span class="hl kwb">const</span>
+<span class="hl opt">{</span>
+ <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>flags<span class="hl opt">);</span>
+
+ QByteArray inputString <span class="hl opt">=</span> <span class="hl kwd">QString</span><span class="hl opt">(</span><span class="hl str">"%1%2"</span><span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>name<span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>masterPassword<span class="hl opt">).</span><span class="hl kwd">toLatin1</span><span class="hl opt">();</span>
+ QCryptographicHash <span class="hl kwd">hash</span><span class="hl opt">(</span>QCryptographicHash<span class="hl opt">::</span>Md5<span class="hl opt">);</span>
+ hash<span class="hl opt">.</span><span class="hl kwd">addData</span><span class="hl opt">(</span>inputString<span class="hl opt">);</span>
+ QByteArray result <span class="hl opt">=</span> hash<span class="hl opt">.</span><span class="hl kwd">result</span><span class="hl opt">().</span><span class="hl kwd">toBase64</span><span class="hl opt">();</span>
+ <span class="hl kwa">if</span> <span class="hl opt">(</span>length <span class="hl opt">></span> <span class="hl num">0</span><span class="hl opt">)</span>
+ <span class="hl kwa">return</span> result<span class="hl opt">.</span><span class="hl kwd">left</span><span class="hl opt">(</span>length<span class="hl opt">);</span>
+ <span class="hl kwa">else</span>
+ <span class="hl kwa">return</span> result<span class="hl opt">;</span>
+<span class="hl opt">}</span></pre>
+
+ <p>We also know now the maximum length of the generated password, which is 24. Go back to the <tt>module.h</tt> header file and
+ modify the <tt>GeneratorImpl::maxLength()</tt> function:</p>
+
+<pre class="hl"><span class="hl kwc">virtual</span> <span class="hl kwb">int</span> <span class="hl kwd">maxLength</span><span class="hl opt">()</span> <span class="hl kwb">const</span> <span class="hl opt">{</span> <span class="hl kwa">return</span> <span class="hl num">24</span><span class="hl opt">; }</span></pre>
+
+ <p>Here is the final <tt>module.cpp</tt> file:</p>
+
+<pre class="hl"><span class="hl com">/**</span>
+<span class="hl com"> * @file src/apps/PswGen/Generator/module.cpp</span>
+<span class="hl com"> */</span>
+
+<span class="hl ppc">#include</span> <span class="hl pps">"module.h"</span><span class="hl ppc"></span>
+<span class="hl ppc">#include</span> <span class="hl pps">"version.h"</span><span class="hl ppc"></span>
+
+<span class="hl ppc">#include <Common/iLogger></span>
+<span class="hl ppc">#include <Common/iRegistry></span>
+
+<span class="hl ppc">#include <QtCore></span>
+
+<span class="hl kwd">VER_EXPORT_VERSION_INFO</span><span class="hl opt">()</span>
+<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>Generator<span class="hl opt">::</span>Module<span class="hl opt">)</span>
+
+<span class="hl kwa">using namespace</span> eVaf<span class="hl opt">;</span>
+<span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">;</span>
+<span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>Generator<span class="hl opt">;</span>
+
+Module<span class="hl opt">::</span><span class="hl kwd">Module</span><span class="hl opt">()</span>
+ <span class="hl opt">:</span> Plugins<span class="hl opt">::</span><span class="hl kwd">iPlugin</span><span class="hl opt">()</span>
+<span class="hl opt">{</span>
+ <span class="hl kwd">setObjectName</span><span class="hl opt">(</span><span class="hl kwd">QString</span><span class="hl opt">(</span><span class="hl str">"%1.%2"</span><span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>VER_MODULE_NAME_STR<span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>__FUNCTION__<span class="hl opt">));</span>
+
+ mGenerator <span class="hl opt">=</span> <span class="hl kwa">new</span> Internal<span class="hl opt">::</span>GeneratorImpl<span class="hl opt">;</span>
+
+ <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s created"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span>
+<span class="hl opt">}</span>
+
+Module<span class="hl opt">::~</span><span class="hl kwd">Module</span><span class="hl opt">()</span>
+<span class="hl opt">{</span>
+ <span class="hl kwa">delete</span> mGenerator<span class="hl opt">;</span>
+
+ <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s destroyed"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span>
+<span class="hl opt">}</span>
+
+<span class="hl kwb">bool</span> Module<span class="hl opt">::</span><span class="hl kwd">init</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> args<span class="hl opt">)</span>
+<span class="hl opt">{</span>
+ <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>args<span class="hl opt">);</span>
+
+ <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s initialized"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span>
+
+ <span class="hl kwa">return true</span><span class="hl opt">;</span>
+<span class="hl opt">}</span>
+
+<span class="hl kwb">void</span> Module<span class="hl opt">::</span><span class="hl kwd">done</span><span class="hl opt">()</span>
+<span class="hl opt">{</span>
+ <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s finalized"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span>
+<span class="hl opt">}</span>
+
+<span class="hl kwa">using namespace</span> eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>Generator<span class="hl opt">::</span>Internal<span class="hl opt">;</span>
+
+GeneratorImpl<span class="hl opt">::</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">()</span>
+ <span class="hl opt">:</span> <span class="hl kwd">iGenerator</span><span class="hl opt">()</span>
+<span class="hl opt">{</span>
+ <span class="hl kwd">setObjectName</span><span class="hl opt">(</span><span class="hl kwd">QString</span><span class="hl opt">(</span><span class="hl str">"%1.iGenerator"</span><span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>VER_MODULE_NAME_STR<span class="hl opt">));</span>
+
+ Common<span class="hl opt">::</span>iRegistry<span class="hl opt">::</span><span class="hl kwd">instance</span><span class="hl opt">()-></span><span class="hl kwd">registerInterface</span><span class="hl opt">(</span><span class="hl str">"iGenerator"</span><span class="hl opt">,</span> <span class="hl kwa">this</span><span class="hl opt">);</span>
+
+ <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s created"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span>
+<span class="hl opt">}</span>
+
+GeneratorImpl<span class="hl opt">::~</span><span class="hl kwd">GeneratorImpl</span><span class="hl opt">()</span>
+<span class="hl opt">{</span>
+ <span class="hl kwd">EVAF_INFO</span><span class="hl opt">(</span><span class="hl str">"%s destroyed"</span><span class="hl opt">,</span> <span class="hl kwd">qPrintable</span><span class="hl opt">(</span><span class="hl kwd">objectName</span><span class="hl opt">()));</span>
+<span class="hl opt">}</span>
+
+QString GeneratorImpl<span class="hl opt">::</span><span class="hl kwd">generatePassword</span><span class="hl opt">(</span>QString <span class="hl kwb">const</span> <span class="hl opt">&</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&</span> masterPassword<span class="hl opt">,</span> <span class="hl kwb">int</span> length<span class="hl opt">,</span> uint flags<span class="hl opt">)</span> <span class="hl kwb">const</span>
+<span class="hl opt">{</span>
+ <span class="hl kwd">Q_UNUSED</span><span class="hl opt">(</span>flags<span class="hl opt">);</span>
+
+ QByteArray inputString <span class="hl opt">=</span> <span class="hl kwd">QString</span><span class="hl opt">(</span><span class="hl str">"%1%2"</span><span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>name<span class="hl opt">).</span><span class="hl kwd">arg</span><span class="hl opt">(</span>masterPassword<span class="hl opt">).</span><span class="hl kwd">toLatin1</span><span class="hl opt">();</span>
+ QCryptographicHash <span class="hl kwd">hash</span><span class="hl opt">(</span>QCryptographicHash<span class="hl opt">::</span>Md5<span class="hl opt">);</span>
+ hash<span class="hl opt">.</span><span class="hl kwd">addData</span><span class="hl opt">(</span>inputString<span class="hl opt">);</span>
+ QByteArray result <span class="hl opt">=</span> hash<span class="hl opt">.</span><span class="hl kwd">result</span><span class="hl opt">().</span><span class="hl kwd">toBase64</span><span class="hl opt">();</span>
+ <span class="hl kwa">if</span> <span class="hl opt">(</span>length <span class="hl opt">></span> <span class="hl num">0</span><span class="hl opt">)</span>
+ <span class="hl kwa">return</span> result<span class="hl opt">.</span><span class="hl kwd">left</span><span class="hl opt">(</span>length<span class="hl opt">);</span>
+ <span class="hl kwa">else</span>
+ <span class="hl kwa">return</span> result<span class="hl opt">;</span>
+<span class="hl opt">}</span></pre>
+
+ <p>Next -- <a href="pswgen05.html">05 - Building Generator Module</a>.</p>
+
+ </body>
+</html>
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang="et" xmlns="http://www.w3.org/1999/xhtml" xml:lang="et">
+
+ <head>
+ <meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />
+ <title>eVaf Tutorial - 05 - Building Generator Module</title>
+ <meta name="Author" content="Enar Väikene" />
+ <meta name="description" content="eVaf Tutorial" />
+ <meta name="keywords" content="evaf c++ application development framework tutorial password generator" />
+ <link rel="StyleSheet" href="evaf.css" type="text/css" media="all" />
+ <link rel="StyleSheet" href="highlight.css" type="text/css" media="all" />
+ </head>
+
+ <body>
+
+ <h1>eVaf Tutorial</h1>
+
+ <h2>05 - Building Generator Module</h2>
+
+ <h3>CMakeLists.txt</h3>
+
+ <p>eVaf uses <a href="http://www.cmake.org">CMake</a> as its build system and needs a file called <tt>CMakeLists.txt</tt>
+ in the <tt>src/apps/PswGen/Generator</tt> directory. Create the file and start editing it.</p>
+
+ <p>We use the <tt>TARGET</tt> variable to set the name of the module. This makes it easier to re-use the <tt>CMakeLists.txt</tt>
+ file in other modules and applications.</p>
+
+<pre class="hl"><span class="hl kwa">set</span><span class="hl opt">(</span>TARGET PswGen<span class="hl opt">)</span></pre>
+
+ <p>Then we include Qt include files and libraries. We also specify, that we do not want to include the QtGui module as this
+ module does not any classes from the QtGui module. By removing the QtGui module, we remove any graphical libraries as
+ dependencies for this module and it can be used in headless systems.</p>
+
+<pre class="hl"><span class="hl kwa">set</span><span class="hl opt">(</span>QT_DONT_USE_QTGUI TRUE<span class="hl opt">)</span>
+<span class="hl kwa">include</span><span class="hl opt">(</span><span class="hl kwd">${QT_USE_FILE}</span><span class="hl opt">)</span></pre>
+
+ <p>The next line adds the <tt>PSWGEN_GENERATOR_LIBRARY</tt> definition to the compiler (remember the <tt>lib.h</tt> file and
+ the <tt>PSWGEN_GENERATOR_EXPORT</tt> macro in the <tt>igeneraror.h</tt> file?):
+
+<pre class="hl"><span class="hl kwa">add_definitions</span><span class="hl opt">(</span>-DPSWGEN_GENERATOR_LIBRARY<span class="hl opt">)</span></pre>
+
+ <p>Add all the eVaf include directories to the compiler. The variable <tt>eVaf_INCLUDE</tt> contains all the eVaf include
+ directories and is already initialized with proper values when this <tt>CMakeLists.txt</tt> file is processed.</p>
+
+<pre class="hl"><span class="hl kwa">include_directories</span><span class="hl opt">(</span><span class="hl kwd">${eVaf_INCLUDE}<span class="hl opt">)</span></pre>
+
+ <p>Then we initialize a variable with the names of all the eVaf modules that this module needs to be linked with. We only
+ need to specify the names of libraries without prefixes or suffixes like ".dll" or ".so". These libraries also become dependencies
+ of this module and will be built whenever we build this module.</p>
+
+<pre class="hl"><span class="hl kwa">set</span><span class="hl opt">(</span>eVaf_LIBRARIES CommonLib PluginsLib<span class="hl opt">)</span></pre>
+
+ <p>Collect all the source files that needs to be compiled:</p>
+
+<pre class="hl"><span class="hl kwa">set</span><span class="hl opt">(</span>SRCS
+ module.cpp
+<span class="hl opt">)</span></pre>
+
+ <p>Collect header files that need to be processed with the Qt meta-object compiler. Any header file that contains
+ class declarations with the Q_OBJECT keyword and/or signals and slots, needs to be included here. To avoid warnings
+ during the build, do not include here any other header files.</p>
+
+<pre class="hl"><span class="hl kwa">set</span><span class="hl opt">(</span>MOC_HDRS
+ igenerator.h
+ module.h
+<span class="hl opt">)</span></pre>
+
+ <p>The following line adds the Windows version info resource file to the list of source files:</p>
+<pre class="hl"><span class="hl kwa">if</span><span class="hl opt">(</span><span class="hl kwb">WIN32</span><span class="hl opt">)</span>
+ <span class="hl kwa">set</span><span class="hl opt">(</span>SRCS <span class="hl kwd">${SRCS}</span> version.rc<span class="hl opt">)</span>
+<span class="hl kwa">endif</span><span class="hl opt">(</span><span class="hl kwb">WIN32</span><span class="hl opt">)</span></pre>
+
+ <p>Process specified header files with the Qt meta-object compiler:</p>
+
+<pre class="hl"><span class="hl kwd">qt4_wrap_cpp</span><span class="hl opt">(</span>MOC_SRCS <span class="hl kwd">${MOC_HDRS}</span><span class="hl opt">)</span></pre>
+
+ <p>Put it all together and compile the module:</p>
+
+<pre class="hl"><span class="hl kwa">add_library</span><span class="hl opt">(</span><span class="hl kwd">${TARGET}</span> <span class="hl kwb">SHARED</span> <span class="hl kwd">${SRCS} ${MOC_SRCS}</span><span class="hl opt">)</span></pre>
+
+ <p>Finally, link the module:</p>
+
+<pre class="hl"><span class="hl kwa">target_link_libraries</span><span class="hl opt">(</span><span class="hl kwd">${TARGET} ${QT_LIBRARIES} ${eVaf_LIBRARIES}</span><span class="hl opt">)</span></pre>
+
+ <p>And the final <tt>CMakeLists.txt</tt> file looks the following:</p>
+
+<pre class="hl"><span class="hl com"># src/apps/PswGen/Generator/CMakeLists.txt</span>
+
+<span class="hl com"># Name of the target</span>
+<span class="hl kwa">set</span><span class="hl opt">(</span>TARGET PswGen<span class="hl opt">)</span>
+
+<span class="hl com"># Qt modules</span>
+<span class="hl kwa">set</span><span class="hl opt">(</span>QT_DONT_USE_QTGUI TRUE<span class="hl opt">)</span>
+<span class="hl kwa">include</span><span class="hl opt">(</span><span class="hl kwd">${QT_USE_FILE}</span><span class="hl opt">)</span>
+
+<span class="hl com"># Needed for exporting symbols from this library</span>
+<span class="hl kwa">add_definitions</span><span class="hl opt">(</span>-DPSWGEN_GENERATOR_LIBRARY<span class="hl opt">)</span>
+
+<span class="hl com"># Include directories</span>
+<span class="hl kwa">include_directories</span><span class="hl opt">(</span><span class="hl kwd">${eVaf_INCLUDE}<span class="hl opt">)</span>
+
+<span class="hl com"># Required eVaf libraries</span>
+<span class="hl kwa">set</span><span class="hl opt">(</span>eVaf_LIBRARIES CommonLib PluginsLib<span class="hl opt">)</span>
+
+<span class="hl com"># Source files</span>
+<span class="hl kwa">set</span><span class="hl opt">(</span>MOC_HDRS
+ igenerator.h
+ module.h
+<span class="hl opt">)</span>
+
+<span class="hl com"># Header files for the Qt meta-object compiler</span>
+<span class="hl kwa">set</span><span class="hl opt">(</span>MOC_HDRS
+ igenerator.h
+ module.h
+<span class="hl opt">)</span>
+
+<span class="hl com"># Version info resource file for Windows builds</span>
+<span class="hl kwa">if</span><span class="hl opt">(</span><span class="hl kwb">WIN32</span><span class="hl opt">)</span>
+ <span class="hl kwa">set</span><span class="hl opt">(</span>SRCS <span class="hl kwd">${SRCS}</span> version.rc<span class="hl opt">)</span>
+<span class="hl kwa">endif</span><span class="hl opt">(</span><span class="hl kwb">WIN32</span><span class="hl opt">)</span>
+
+<span class="hl com"># Run the Qt meta-object compiler</span>
+<span class="hl kwd">qt4_wrap_cpp</span><span class="hl opt">(</span>MOC_SRCS <span class="hl kwd">${MOC_HDRS}</span><span class="hl opt">)</span>
+
+<span class="hl com"># Compile the module</span>
+<span class="hl kwa">add_library</span><span class="hl opt">(</span><span class="hl kwd">${TARGET}</span> <span class="hl kwb">SHARED</span> <span class="hl kwd">${SRCS} ${MOC_SRCS}</span><span class="hl opt">)</span>
+
+<span class="hl com"># Link the module</span>
+<span class="hl kwa">target_link_libraries</span><span class="hl opt">(</span><span class="hl kwd">${TARGET} ${QT_LIBRARIES} ${eVaf_LIBRARIES}</span><span class="hl opt">)</span></pre>
+
+ <p>We also need <tt>CMakeLists.txt</tt> files in parent directory <tt>src/apps/PswGen</tt>.
+ In this file we add the <tt>PswGen</tt> directory to the list of include directories, which makes it possible to use
+
+<pre class="hl"><span class="hl com"># src/apps/PswGen/CMakeLists.txt</span>
+<span class="hl kwa">set</span><span class="hl opt">(</span>eVaf_INCLUDE <span class="hl kwd">${eVaf_INCLUDE} ${SMAKE_SOURCE_DIR}</span>/src/apps/PswGen<span class="hl opt">)</span>
+<span class="hl kwa">add_subdirectory</span><span class="hl opt">(</span>Generator<span class="hl opt">)</span></pre>
+
+ <p>Modify the <tt>CMakeLists.txt</tt> file in the <tt>src/apps</tt> directory and include the <tt>PswGen</tt> application:</p>
+
+<pre class="hl"><span class="hl com"># src/apps/CMakeLists.txt</span>
+<span class="hl com"># ...</span>
+<span class="hl kwa">add_subdirectory</span><span class="hl opt">(</span>PswGen<span class="hl opt">)</span></pre>
+
+ <h3>Building the module</h3>
+
+ <p>Now our module is included in the build system and we can try to compile it. Go to the eVaf root directory and create
+ a build directory:</p>
+
+<pre>evaf $ <code>mkdir build</code>
+evaf $ <code>cd build</code></pre>
+
+ <p>In the build directory, run <tt>cmake</tt>:</p>
+
+<pre>evaf/build $ <code>cmake ..</code></pre>
+
+ <p>If <tt>cmake</tt> finishes without errors, build the module with the <tt>make</tt> command:</p>
+
+<pre>evaf/build $ <code>make PswGen</code></pre>
+
+ <p>If you get compiler errors during the build, fix them. If the build finishes without errors, check the content of the
+ <tt>bin</tt> directory:</p>
+
+<pre>evaf/build $ <code>ls bin</code>
+libCommonLib.so* libPluginsLib.so* libPswGen.so*
+evaf/build $</pre>
+
+ <p>As you can see, there are three libraries now. The <tt>libPswGen.so</tt> is our module and others are eVaf libraries
+ that our module needs in order to be run.</p>
+
+ <p>In the next section <a href="pswgen06.html">06 - Storage Module</a> we write the Storage module.
+
+ </body>
+</html>