]> vaikene.ee Git - evaf/commitdiff
Changed tutorial files to follow the changes in the PswGen application.
authorEnar Väikene <enar@vaikene.net>
Thu, 28 Jul 2011 13:44:13 +0000 (16:44 +0300)
committerEnar Väikene <enar@vaikene.net>
Thu, 28 Jul 2011 13:44:13 +0000 (16:44 +0300)
- Interfaces in this application are now pure abstract classes.

www/pswgen03.html
www/pswgen04.html
www/pswgen05.html

index 056da8e42145a4b3c1f15656e206c67b8cb92497..88597303ef115b5dd96da7dc8187875d7be021d0 100644 (file)
@@ -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 &lt;QObject&gt;</span>
 <span class="hl ppc">#include &lt;QString&gt;</span></pre>
 <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">&amp;</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&amp;</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>
 
         <p>I am training myself to use the style of writing declarations like <tt>"QString const &amp;"</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 &amp;"</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"> * &#64;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 &lt;QtCore/qglobal.h&gt;</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&lt;&gt;()</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">&quot;lib.h&quot;</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">&quot;eVaf.PswGen.iGenerator/1.0&quot;</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>
 
 <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">&quot;lib.h&quot;</span><span class="hl ppc"></span>
-
 <span class="hl ppc">#include &lt;QObject&gt;</span>
 <span class="hl ppc">#include &lt;QString&gt;</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 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">&amp;</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&amp;</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 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">&quot;eVaf.PswGen.iGenerator/1.0&quot;</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">&quot;igenerator.h&quot;</span><span class="hl ppc"></span></pre>
 <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>
 
 }</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>
 
 <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>
 
     <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>
 
 
     <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>
 
 
     <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">&amp;</span> name<span class="hl opt">,</span> QString <span class="hl kwb">const</span> <span class="hl opt">&amp;</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>
index df82cb0b946a970ac9d1335fee64c395576e05c1..bf8804683831de7aea9766dec88bc3edf49e560e 100644 (file)
 
 <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>
index bc6b5d6545d1b5d70f1065cce92d414c537efd85..d84504d70d2e4b5467eef76466871a3283742bfd 100644 (file)
 <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>
 
 <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>