From 14d19e80570564c2cdbe9ca6feba246fa994a250 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Enar=20V=C3=A4ikene?= <enar@vaikene.net> Date: Thu, 28 Jul 2011 16:44:13 +0300 Subject: [PATCH] Changed tutorial files to follow the changes in the PswGen application. - Interfaces in this application are now pure abstract classes. --- www/pswgen03.html | 102 +++++++++++++++------------------------------- www/pswgen04.html | 5 +++ www/pswgen05.html | 15 +------ 3 files changed, 40 insertions(+), 82 deletions(-) diff --git a/www/pswgen03.html b/www/pswgen03.html index 056da8e..8859730 100644 --- a/www/pswgen03.html +++ b/www/pswgen03.html @@ -23,7 +23,7 @@ <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 + <p>We start by defining the interface for the module and 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> @@ -34,8 +34,8 @@ <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> + <p>We need to include some Qt header files -- <tt>QObject</tt> is almost always needed and <tt>QString</tt> we need 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> @@ -49,23 +49,15 @@ <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>: + <p>We call the interface class <tt>iGenerator</tt>. For pure abstract classes I personally prefer using the <tt>struct</tt> keyword, but + <tt>class</tt> works as well if you remember to add the <tt>public</tt> keyword to make methods in the class public.</p> - <pre class="hl"><span class="hl kwc">class</span> iGenerator <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject + <pre class="hl"><span class="hl kwc">struct</span> iGenerator <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> +<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 + <p>We add 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> @@ -74,29 +66,10 @@ <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> + <p>We use the <tt>Q_DECLARE_INTERFACE</tt> macro to add Qt meta-data to the interface. eVaf interfaces are type-casted using the <tt>qobject_cast<>()</tt> template function and it requires meta-data to verify type and version of the interface. The <tt>Q_DECLARE_INTERFACE</tt> macro has to be + outside of any namespaces and we add it to the end of the file:</p> -<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> + <pre class="hl"><span class="hl kwd">Q_DECLARE_INTERFACE</span><span class="hl opt">(</span>eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>iGenerator<span class="hl opt">,</span> <span class="hl str">"eVaf.PswGen.iGenerator/1.0"</span><span class="hl opt">)</span></pre> <p>This is pretty much all we need to add to the <tt>iGenerator</tt> interface and here is the final file:</p> @@ -107,8 +80,6 @@ <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> @@ -116,18 +87,8 @@ <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 kwb">struct</span> iGenerator <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> @@ -139,8 +100,9 @@ <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> +<span class="hl kwd">Q_DECLARE_INTERFACE</span><span class="hl opt">(</span>eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>iGenerator<span class="hl opt">,</span> <span class="hl str">"eVaf.PswGen.iGenerator/1.0"</span><span class="hl opt">)</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> @@ -191,8 +153,7 @@ <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> + <tt>eVaf::PswGen::Generator</tt> namespace</tt>.</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> @@ -206,8 +167,8 @@ }</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 + <p>The <tt>iPlugin</tt> interface has three pure virtual 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 always <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> @@ -232,11 +193,15 @@ <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> + <tt>GeneratorImpl</tt>. This class goes into the <tt>eVaf::PswGen::Generator::Internal</tt> namespace.</p> + + <p>The <tt>GeneratorImpl</tt> class needs to be derived both from <tt>QObject</tt> and from <tt>iGenerator</tt>. We also have to use the + <tt>Q_INTERFACES</tt> macro to include Qt meta-data for the <tt>iGenerator</tt> interface:</p> -<pre class="hl"><span class="hl kwc">class</span> GeneratorImpl <span class="hl opt">:</span> <span class="hl kwc">public</span> iGenerator +<pre class="hl"><span class="hl kwc">class</span> GeneratorImpl <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject<span class="hl opt">,</span> <span class="hl kwc">public</span> iGenerator <span class="hl opt">{</span> - Q_OBJECT + <span class="hl kwd">Q_OBJECT</span> + <span class="hl kwd">Q_INTERFACES</span><span class="hl opt">(</span>eVaf::PswGen::iGenerator<span class="hl opt">)</span> <span class="hl kwc">public</span><span class="hl opt">:</span> @@ -276,10 +241,10 @@ <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 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 kwd">Q_OBJECT</span> <span class="hl kwc">public</span><span class="hl opt">:</span> @@ -293,20 +258,19 @@ <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 com">/// iGenerator interface implementation.</span> +<span class="hl kwc">class</span> GeneratorImpl <span class="hl opt">:</span> <span class="hl kwc">public</span> QObject<span class="hl opt">,</span> <span class="hl kwc">public</span> iGenerator <span class="hl opt">{</span> - Q_OBJECT + <span class="hl kwd">Q_OBJECT</span> + <span class="hl kwd">Q_INTERFACES</span><span class="hl opt">(</span>eVaf<span class="hl opt">::</span>PswGen<span class="hl opt">::</span>iGenerator<span class="hl opt">)</span> <span class="hl kwc">public</span><span class="hl opt">:</span> @@ -316,11 +280,11 @@ <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 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> <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> diff --git a/www/pswgen04.html b/www/pswgen04.html index df82cb0..bf88046 100644 --- a/www/pswgen04.html +++ b/www/pswgen04.html @@ -93,6 +93,11 @@ <span class="hl kwd">VER_EXPORT_VERSION_INFO</span><span class="hl opt">()</span></pre> + <p>To make the <tt>Module</tt> class a proper Qt plugin, we use the <tt>Q_EXPORT_PLUGIN2</tt> macro. The name of the module is already + defined in the <tt>version.h</tt> header file as <tt>VER_MODULE_NAME_STR</tt>. + + <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>Generator<span class="hl opt">::</span>Module<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> diff --git a/www/pswgen05.html b/www/pswgen05.html index bc6b5d6..d84504d 100644 --- a/www/pswgen05.html +++ b/www/pswgen05.html @@ -34,11 +34,6 @@ <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> @@ -61,7 +56,6 @@ 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> @@ -93,9 +87,6 @@ <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> @@ -103,14 +94,12 @@ <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 kwa">set</span><span class="hl opt">(</span>SRCS + module.cpp <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> -- 2.49.0