From: Enar Väikene 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: 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: 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. 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. 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: 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: 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: 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: This is pretty much all we need to add to the iGenerator interface and here is the final file: As a final touch, we create a file called iGenerator with the following content: 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.iGenerator interface
- /**
@@ -34,8 +34,8 @@
#endif // igenerator.h
- #include <QObject>
#include <QString>
@@ -49,23 +49,15 @@
} // namespace eVaf::PswGen
} // namespace eVaf
- class iGenerator : public QObject
+
- struct iGenerator
{
- Q_OBJECT
-public:
-};
-
- /// Interface constructor
-iGenerator() : QObject() {}
-/// Empty virtual destructor
-virtual ~iGenerator() {}
+};virtual QString generatePassword(QString const & name, QString const & masterPassword, int length, uint flags = 0) const = 0;
@@ -74,29 +66,10 @@
+Q_DECLARE_INTERFACE(eVaf::PswGen::iGenerator, "eVaf.PswGen.iGenerator/1.0")
+
+#endif // igenerator.h
/**
- * @file src/apps/PswGen/Generator/lib.h
- */
-#ifndef __PSWGEN_GENERATOR_LIB_H
-# define __PSWGEN_GENERATOR_LIB_H
-
-#include <QtCore/qglobal.h>
+
-
- #include "lib.h"
-
-/// ...
-
-class PSWGEN_GENERATOR_EXPORT iGenerator : public QObject
+ Q_DECLARE_INTERFACE(eVaf::PswGen::iGenerator, "eVaf.PswGen.iGenerator/1.0")
#include "igenerator.h"
@@ -191,8 +153,7 @@
} // namespace eVaf
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 )