From: Enar Väikene Date: Thu, 28 Jul 2011 13:44:13 +0000 (+0300) Subject: Changed tutorial files to follow the changes in the PswGen application. X-Git-Url: https://vaikene.ee/gitweb/index.html?a=commitdiff_plain;h=14d19e80570564c2cdbe9ca6feba246fa994a250;p=evaf Changed tutorial files to follow the changes in the PswGen application. - Interfaces in this application are now pure abstract classes. --- 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 @@

iGenerator interface

-

We start by defining the interface for the module. For this create the file igenerator.h in the +

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

/**
@@ -34,8 +34,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 +49,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 +66,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 +80,6 @@ #ifndef __PSWGEN_GENERATOR_IGENERATOR_H # define __PSWGEN_GENERATOR_IGENERATOR_H -#include "lib.h" - #include <QObject> #include <QString> @@ -116,18 +87,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 +100,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 +153,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 +167,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 +193,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 +241,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 +258,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 +280,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
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 @@
 
 VER_EXPORT_VERSION_INFO()
+

To make the Module class a proper Qt plugin, we use the Q_EXPORT_PLUGIN2 macro. The name of the module is already + defined in the version.h header file as VER_MODULE_NAME_STR. + +

Q_EXPORT_PLUGIN2(VER_MODULE_NAME_STR, eVaf::PswGen::Generator::Module)
+

We make our life easier with several using namespace keywords:

using namespace eVaf;
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 @@
 
set(QT_DONT_USE_QTGUI TRUE)
 include(${QT_USE_FILE})
-

The next line adds the PSWGEN_GENERATOR_LIBRARY definition to the compiler (remember the lib.h file and - the PSWGEN_GENERATOR_EXPORT macro in the igeneraror.h file?): - -

add_definitions(-DPSWGEN_GENERATOR_LIBRARY)
-

Add all the eVaf include directories to the compiler. The variable eVaf_INCLUDE contains all the eVaf include directories and is already initialized with proper values when this CMakeLists.txt file is processed.

@@ -61,7 +56,6 @@ during the build, do not include here any other header files.

set(MOC_HDRS
-    igenerator.h
     module.h
 )
@@ -93,9 +87,6 @@ set(QT_DONT_USE_QTGUI TRUE) include(${QT_USE_FILE}) -# Needed for exporting symbols from this library -add_definitions(-DPSWGEN_GENERATOR_LIBRARY) - # Include directories include_directories(${eVaf_INCLUDE}) @@ -103,14 +94,12 @@ set(eVaf_LIBRARIES CommonLib PluginsLib) # Source files -set(MOC_HDRS - igenerator.h - module.h +set(SRCS + module.cpp ) # Header files for the Qt meta-object compiler set(MOC_HDRS - igenerator.h module.h )