X-Git-Url: https://vaikene.ee/gitweb/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=www%2Fpswgen03.html;h=a4bd834943764d8cafe13ea8ab079a7af815e152;hb=0a729a60ff7d40813f2f871ec973a7ff4a191684;hp=056da8e42145a4b3c1f15656e206c67b8cb92497;hpb=368818c22af812ac35f5ff69423522dbd54d37ed;p=evaf diff --git a/www/pswgen03.html b/www/pswgen03.html index 056da8e..a4bd834 100644 --- a/www/pswgen03.html +++ b/www/pswgen03.html @@ -13,6 +13,7 @@ +

Next: 04 - Generator Module, Previous: 02 - Preparations

eVaf Tutorial

03 - Generator Module

@@ -23,8 +24,8 @@

iGenerator interface

-

We start by defining the interface for the module. For this create the file igenerator.h in the - src/apps/pswGen/Generator directory:

+

We start by defining the interface for the module and create the file igenerator.h in the + src/apps/PswGen/Generator directory:

/**
  * @file src/apps/PswGen/Generator/igenerator.h
@@ -34,8 +35,8 @@
 
 #endif // igenerator.h
-

The interface class needs to be derived from QObject and we also need QString for input - data and generated passwords:

+

We need to include some Qt header files -- QObject is almost always needed and QString we need for input data and generated + passwords:

#include <QObject>
 #include <QString>
@@ -49,23 +50,15 @@ } // namespace eVaf::PswGen } // namespace eVaf -

We call the interface class iGenerator: +

We call the interface class iGenerator. For pure abstract classes I personally prefer using the struct keyword, but + class works as well if you remember to add the public keyword to make methods in the class public.

-
class iGenerator : public QObject
+        
struct iGenerator
 {
-    Q_OBJECT
-public:
-};
- -

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.

-
/// Interface constructor
-iGenerator() : QObject() {}
 
-/// Empty virtual destructor
-virtual ~iGenerator() {}
+};
-

Now we add the functionality to the interface and according to the specification we need two functions -- one that +

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:

virtual QString generatePassword(QString const & name, QString const & masterPassword, int length, uint flags = 0) const = 0;
@@ -74,29 +67,10 @@
 
         

I am training myself to use the style of writing declarations like "QString const &", which refers to a non-mutable QString object similar to "int maxLength() const", which is a function that does not modify the object's data members. Feel free to use the traditional way of writing "const QString &" if this looks weird to you.

-

The iGenerator interface needs to be visible for other modules and marked for export. We do this by creating the src/apps/PswGen/Generator/lib.h file, which defines the PSWGEN_GENERATOR_EXPORT macro:

-
/**
- * @file src/apps/PswGen/Generator/lib.h
- */
-#ifndef __PSWGEN_GENERATOR_LIB_H
-#  define __PSWGEN_GENERATOR_LIB_H
-
-#include <QtCore/qglobal.h>
+        

We use the Q_DECLARE_INTERFACE macro to add Qt meta-data to the interface. eVaf interfaces are type-casted using the qobject_cast<>() template function and it requires meta-data to verify type and version of the interface. The Q_DECLARE_INTERFACE macro has to be + outside of any namespaces and we add it to the end of the file:

-#if defined(PSWGEN_GENERATOR_LIBRARY) -# define PSWGEN_GENERATOR_EXPORT Q_DECL_EXPORT -#else -# define PSWGEN_GENERATOR_EXPORT Q_DECL_IMPORT -#endif -#endif // libgen.h
- -

Then we include this new header file in our interface header file and modify the iGenerator class definition by adding - the PSWGEN_GENERATOR_EXPORT macro to it:

-
#include "lib.h"
-
-/// ...
-
-class PSWGEN_GENERATOR_EXPORT iGenerator : public QObject
+
Q_DECLARE_INTERFACE(eVaf::PswGen::iGenerator, "eVaf.PswGen.iGenerator/1.0")

This is pretty much all we need to add to the iGenerator interface and here is the final file:

@@ -107,8 +81,6 @@ #ifndef __PSWGEN_GENERATOR_IGENERATOR_H # define __PSWGEN_GENERATOR_IGENERATOR_H -#include "lib.h" - #include <QObject> #include <QString> @@ -116,18 +88,8 @@ namespace PswGen { /// Password generator interface. -class PSWGEN_GENERATOR_EXPORT iGenerator : public QObject +struct iGenerator { - Q_OBJECT - -public: - - /// Interface constructor - iGenerator() : QObject() {} - - /// Empty virtual destructor - virtual ~iGenerator() {} - /// Generates a strong password virtual QString generatePassword(QString const & name, QString const & masterPassword, int length, uint flags = 0) const = 0; @@ -139,8 +101,9 @@ } // namespace eVaf::PswGen } // namespace eVaf -#endif // igenerator.h -
+Q_DECLARE_INTERFACE(eVaf::PswGen::iGenerator, "eVaf.PswGen.iGenerator/1.0") + +#endif // igenerator.h

As a final touch, we create a file called iGenerator with the following content:

#include "igenerator.h"
@@ -191,8 +154,7 @@ } // namespace eVaf

We call the class that implements the module simply Module. This is a public class and goes into the - eVaf::PswGen::Generator namespace. We however, do not need to export it as we did with the iGenerator - interface class, as this will be done by Qt.

+ eVaf::PswGen::Generator namespace.

class Module : public Plugins::iPlugin
 {
@@ -206,8 +168,8 @@
 
 }
-

The iPlugin interface has three abstract methods that we need to implement in our class -- init(), - done() and isReady(). Since this simple module is always ready, we can return true in the +

The iPlugin interface has three pure virtual methods that we need to implement in our class -- init(), + done() and isReady(). Since this simple module is always ready, we can return always true in the isReady() function. More complex modules can use a private mReady variable, which they set to true once all the initialization is done. @@ -232,11 +194,15 @@ } // namespace eVaf::PswGen::Generator::Internal

Then we can move forward and implement the iGenerator interface, which we already happened to call - GeneratorImpl. This class goes into the eVaf::PswGen::Generator::Internal namespace:

+ GeneratorImpl. This class goes into the eVaf::PswGen::Generator::Internal namespace.

+ +

The GeneratorImpl class needs to be derived both from QObject and from iGenerator. We also have to use the + Q_INTERFACES macro to include Qt meta-data for the iGenerator interface:

-
class GeneratorImpl : public iGenerator
+
class GeneratorImpl : public QObject, public iGenerator
 {
-    Q_OBJECT
+    Q_OBJECT
+    Q_INTERFACES(eVaf::PswGen::iGenerator)
 
 public:
 
@@ -276,10 +242,10 @@
     class GeneratorImpl;
 } // namespace eVaf::PswGen::Generator::Internal
 
-/// Plugins/iPlugin interface implementation.
+/// Plugins::iPlugin interface implementation.
 class Module : public Plugins::iPlugin
 {
-    Q_OBJECT
+    Q_OBJECT
 
 public:
 
@@ -293,20 +259,19 @@
 
     virtual bool isReady() const { return true; }
 
-
 private: // Members
 
     /// iGenerator interface instance
     Internal::GeneratorImpl * mGenerator;
-
 };
 
 namespace Internal {
 
- /// iGenerator interface implementation.
-class GeneratorImpl : public iGenerator
+/// iGenerator interface implementation.
+class GeneratorImpl : public QObject, public iGenerator
 {
-    Q_OBJECT
+    Q_OBJECT
+    Q_INTERFACES(eVaf::PswGen::iGenerator)
 
 public:
 
@@ -316,11 +281,11 @@
 
     virtual QString generatePassword(QString const & name, QString const & masterPassword, int length, uint flags = 0) const;
 
-    virtual int maxLength() const;
-
+    virtual int maxLength() const { return 24; }
 };
 
 } // namespace eVaf::PswGen::Generator::Internal
+
 } // namespace eVaf::PswGen::Generator
 } // namespace eVaf::PswGen
 } // namespace eVaf