1 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html lang=
"et" xmlns=
"http://www.w3.org/1999/xhtml" xml:
lang=
"et">
5 <meta http-equiv=
"CONTENT-TYPE" content=
"text/html; charset=utf-8" />
6 <title>eVaf Tutorial -
09 - GUI Module
</title>
7 <meta name=
"Author" content=
"Enar Väikene" />
8 <meta name=
"description" content=
"eVaf Tutorial" />
9 <meta name=
"keywords" content=
"evaf c++ application development framework tutorial password generator" />
10 <link rel=
"StyleSheet" href=
"evaf.css" type=
"text/css" media=
"all" />
11 <link rel=
"StyleSheet" href=
"highlight.css" type=
"text/css" media=
"all" />
16 <p>Next:
<a href=
"pswgen10.html">10 - GUI Module
</a>, Previous:
<a href=
"pswgen08.html">08 - Building Storage Module
</a></p>
18 <h1>eVaf Tutorial
</h1>
20 <h2>09 - GUI Module
</h2>
22 <p>The Graphical User Interface (
<tt>GUI
</tt>) module implements the main window of the application. It uses previously
23 created
<tt>Generator
</tt> and
<tt>Storage
</tt> modules to generate and store passwords.
</p>
25 <p>We start by creating the
<tt>gui.h
</tt> file in the
<tt>src/apps/PswGen/GUI
</tt> directory:
</p>
27 <pre class=
"hl"><span class=
"hl com">/**
</span>
28 <span class=
"hl com"> *
@file PswGen/GUI/gui.h
</span>
29 <span class=
"hl com"> */
</span>
31 <span class=
"hl ppc">#ifndef __PSWGEN_GUI_GUI_H
</span>
32 <span class=
"hl ppc"># define __PSWGEN_GUI_GUI_H
</span>
34 <span class=
"hl ppc">#endif
</span> <span class=
"hl slc">// gui.h
</span><span class=
"hl ppc"></span></pre>
36 <p>Include the
<tt>Plugins/iPlugin
</tt> header file as this is going to be a plugin and also
<tt>QObject
</tt> and
37 <tt>QString
</tt> as these are almost always needed:
</p>
39 <pre class=
"hl"><span class=
"hl ppc">#include
<Plugins/iPlugin
></span>
40 <span class=
"hl ppc">#include
<QObject
></span>
41 <span class=
"hl ppc">#include
<QString
></span></pre>
43 <p>We use the
<tt>eVaf::PswGen::GUI
</tt> namespace for this module:
</p>
45 <pre class=
"hl"><span class=
"hl kwa">namespace
</span> eVaf
<span class=
"hl opt">{
</span>
46 <span class=
"hl kwa">namespace
</span> PswGen
<span class=
"hl opt">{
</span>
47 <span class=
"hl kwa">namespace
</span> GUI
<span class=
"hl opt">{
</span>
49 <span class=
"hl opt">}
</span> <span class=
"hl slc">// namespace eVaf::PswGen::GUI
</span>
50 <span class=
"hl opt">}
</span> <span class=
"hl slc">// namespace eVaf::PswGen
</span>
51 <span class=
"hl opt">}
</span> <span class=
"hl slc">// namespace eVaf
</span></pre>
53 <p>The module itself can be implemented as one single class derived from the
<tt>Plugins::iPlugin
</tt> parent class:
</p>
55 <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
56 <span class=
"hl opt">{
</span>
59 <span class=
"hl kwc">public
</span><span class=
"hl opt">:
</span>
61 <span class=
"hl kwd">Module
</span><span class=
"hl opt">();
</span>
63 <span class=
"hl kwc">virtual
</span> <span class=
"hl opt">~
</span><span class=
"hl kwd">Module
</span><span class=
"hl opt">();
</span>
65 <span class=
"hl opt">};
</span></pre>
67 <p>Implement pure virtual methods derived from the parent class. The main GUI window is created in the
<tt>init()
</tt> method
68 and the module can only be ready when the initialization is completed. We use the
<tt>mReady
</tt> flag to indicate this.
</p>
70 <pre class=
"hl"> <span class=
"hl kwc">virtual
</span> <span class=
"hl kwb">bool
</span> <span class=
"hl kwd">init
</span><span class=
"hl opt">(
</span><span class=
"hl kwb">const
</span> QString
<span class=
"hl opt">&</span> args
<span class=
"hl opt">);
</span>
72 <span class=
"hl kwc">virtual
</span> <span class=
"hl kwb">void
</span> <span class=
"hl kwd">done
</span><span class=
"hl opt">();
</span>
74 <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
</span> mReady
<span class=
"hl opt">; }
</span>
76 <span class=
"hl kwc">private
</span><span class=
"hl opt">:
</span>
78 <span class=
"hl kwb">bool
</span> mReady
<span class=
"hl opt">;
</span></pre>
80 <p>In the private members section we store interfaces from previously written modules:
</p>
83 eVaf
<span class=
"hl opt">::
</span>PswGen
<span class=
"hl opt">::
</span>iGenerator
<span class=
"hl opt">*
</span> mGenerator
<span class=
"hl opt">;
</span>
85 eVaf
<span class=
"hl opt">::
</span>PswGen
<span class=
"hl opt">::
</span>iStorage
<span class=
"hl opt">*
</span> mStorage
<span class=
"hl opt">;
</span></pre>
87 <p>Since these are not known yet, we also need to add forward declarations. These go into the
<tt>eVaf::PswGen
</tt> namespace
88 at the beginning of the file:
</p>
91 <span class=
"hl kwa">namespace
</span> eVaf
<span class=
"hl opt">{
</span>
92 <span class=
"hl kwa">namespace
</span> PswGen
<span class=
"hl opt">{
</span>
93 <span class=
"hl kwb">struct
</span> iGenerator
<span class=
"hl opt">;
</span>
94 <span class=
"hl kwb">struct
</span> iStorage
<span class=
"hl opt">;
</span></pre>
96 <p>The main window needs couple of widgets on it:
</p>
99 <li>Master password - a QLineEdit widget;
</li>
100 <li>Name of the password - a QLineEdit widget;
</li>
101 <li>Length of the password - a QSpinBox widget;
</li>
102 <li>Generated password - a QLineEdit widget that we make read-only;
</li>
103 <li>Generate button - a QPushButton widget;
</li>
104 <li>Copy button that copies generated passwords to the clipboard - a QPushButton widget.
</li>
108 <span class=
"hl slc">/// Widgets on the screen
</span>
109 QLineEdit
<span class=
"hl opt">*
</span> wMasterPassword
<span class=
"hl opt">;
</span>
110 QLineEdit
<span class=
"hl opt">*
</span> wName
<span class=
"hl opt">;
</span>
111 QSpinBox
<span class=
"hl opt">*
</span> wLength
<span class=
"hl opt">;
</span>
112 QLineEdit
<span class=
"hl opt">*
</span> wPassword
<span class=
"hl opt">;
</span>
113 QPushButton
<span class=
"hl opt">*
</span> wGenerate
<span class=
"hl opt">;
</span>
114 QPushButton
<span class=
"hl opt">*
</span> wCopy
<span class=
"hl opt">;
</span></pre>
116 <p>Add slots for push buttons:
</p>
118 <pre class=
"hl"><span class=
"hl kwc">private
</span> slots
<span class=
"hl opt">:
</span>
120 <span class=
"hl slc">/// 'Generate' button clicked
</span>
121 <span class=
"hl kwb">void
</span> <span class=
"hl kwd">generateClicked
</span><span class=
"hl opt">();
</span>
123 <span class=
"hl slc">/// 'Copy' button clicked
</span>
124 <span class=
"hl kwb">void
</span> <span class=
"hl kwd">copyClicked
</span><span class=
"hl opt">();
</span></pre>
126 <p>The
<tt>private
</tt> keyword is ignored by the Qt meta-object compiler, but it is a good practice to have it here
127 as an indicator, that these slots are private and should not be used outside of the class.
</p>
129 <p>The
<tt>Generate
</tt> push button should be enabled only when the master password and name are given. Add another
130 slot that will be connected to the
<tt>textChanged()
</tt> signal from these widgets:
</p>
133 <span class=
"hl slc">/// Master password or name changed
</span>
134 <span class=
"hl kwb">void
</span> <span class=
"hl kwd">textChanged
</span><span class=
"hl opt">(
</span>QString
<span class=
"hl kwb">const
</span> <span class=
"hl opt">&);
</span></pre>
136 <p>And here is the final
<tt>gui.h
</tt> file:
</p>
138 <pre class=
"hl"><span class=
"hl com">/**
</span>
139 <span class=
"hl com"> *
@file PswGen/GUI/gui.h
</span>
140 <span class=
"hl com"> */
</span>
141 <span class=
"hl ppc">#ifndef __PSWGEN_GUI_GUI_H
</span>
142 <span class=
"hl ppc"># define __PSWGEN_GUI_GUI_H
</span>
144 <span class=
"hl ppc">#include
<Plugins/iPlugin
></span>
146 <span class=
"hl ppc">#include
<QObject
></span>
147 <span class=
"hl ppc">#include
<QString
></span>
149 <span class=
"hl kwc">class
</span> QLineEdit
<span class=
"hl opt">;
</span>
150 <span class=
"hl kwc">class
</span> QSpinBox
<span class=
"hl opt">;
</span>
151 <span class=
"hl kwc">class
</span> QPushButton
<span class=
"hl opt">;
</span>
153 <span class=
"hl kwa">namespace
</span> eVaf
<span class=
"hl opt">{
</span>
154 <span class=
"hl kwa">namespace
</span> PswGen
<span class=
"hl opt">{
</span>
155 <span class=
"hl kwb">struct
</span> iGenerator
<span class=
"hl opt">;
</span>
156 <span class=
"hl kwb">struct
</span> iStorage
<span class=
"hl opt">;
</span>
157 <span class=
"hl kwa">namespace
</span> GUI
<span class=
"hl opt">{
</span>
159 <span class=
"hl com">/// Graphical User Interface for the PswGen application.
</span>
160 <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
161 <span class=
"hl opt">{
</span>
164 <span class=
"hl kwc">public
</span><span class=
"hl opt">:
</span>
166 <span class=
"hl kwd">Module
</span><span class=
"hl opt">();
</span>
168 <span class=
"hl kwc">virtual
</span> <span class=
"hl opt">~
</span><span class=
"hl kwd">Module
</span><span class=
"hl opt">();
</span>
170 <span class=
"hl kwc">virtual
</span> <span class=
"hl kwb">bool
</span> <span class=
"hl kwd">init
</span><span class=
"hl opt">(
</span><span class=
"hl kwb">const
</span> QString
<span class=
"hl opt">&</span> args
<span class=
"hl opt">);
</span>
172 <span class=
"hl kwc">virtual
</span> <span class=
"hl kwb">void
</span> <span class=
"hl kwd">done
</span><span class=
"hl opt">();
</span>
174 <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
</span> mReady
<span class=
"hl opt">; }
</span>
176 <span class=
"hl kwc">private
</span> slots
<span class=
"hl opt">:
</span>
178 <span class=
"hl slc">/// Master password or name changed
</span>
179 <span class=
"hl kwb">void
</span> <span class=
"hl kwd">textChanged
</span><span class=
"hl opt">(
</span>QString
<span class=
"hl kwb">const
</span> <span class=
"hl opt">&);
</span>
181 <span class=
"hl slc">/// 'Generate' button clicked
</span>
182 <span class=
"hl kwb">void
</span> <span class=
"hl kwd">generateClicked
</span><span class=
"hl opt">();
</span>
184 <span class=
"hl slc">/// 'Copy' button clicked
</span>
185 <span class=
"hl kwb">void
</span> <span class=
"hl kwd">copyClicked
</span><span class=
"hl opt">();
</span>
187 <span class=
"hl kwc">private
</span><span class=
"hl opt">:
</span> <span class=
"hl slc">// Members
</span>
189 <span class=
"hl kwb">static int const
</span> DefaultPasswordLength
<span class=
"hl opt">;
</span>
191 <span class=
"hl slc">/// Flag indicating that the module is ready
</span>
192 <span class=
"hl kwb">bool
</span> mReady
<span class=
"hl opt">;
</span>
194 <span class=
"hl slc">/// The iGenerator interface
</span>
195 eVaf
<span class=
"hl opt">::
</span>PswGen
<span class=
"hl opt">::
</span>iGenerator
<span class=
"hl opt">*
</span> mGenerator
<span class=
"hl opt">;
</span>
197 <span class=
"hl slc">/// The iStorage interface (can be null)
</span>
198 eVaf
<span class=
"hl opt">::
</span>PswGen
<span class=
"hl opt">::
</span>iStorage
<span class=
"hl opt">*
</span> mStorage
<span class=
"hl opt">;
</span>
200 <span class=
"hl slc">/// Widgets on the screen
</span>
201 QLineEdit
<span class=
"hl opt">*
</span> wMasterPassword
<span class=
"hl opt">;
</span>
202 QLineEdit
<span class=
"hl opt">*
</span> wName
<span class=
"hl opt">;
</span>
203 QSpinBox
<span class=
"hl opt">*
</span> wLength
<span class=
"hl opt">;
</span>
204 QLineEdit
<span class=
"hl opt">*
</span> wPassword
<span class=
"hl opt">;
</span>
205 QPushButton
<span class=
"hl opt">*
</span> wGenerate
<span class=
"hl opt">;
</span>
206 QPushButton
<span class=
"hl opt">*
</span> wCopy
<span class=
"hl opt">;
</span>
207 <span class=
"hl opt">};
</span>
209 <span class=
"hl opt">}
</span> <span class=
"hl slc">// namespace eVaf::PswGen::GUI
</span>
210 <span class=
"hl opt">}
</span> <span class=
"hl slc">// namespace eVaf::PswGen
</span>
211 <span class=
"hl opt">}
</span> <span class=
"hl slc">// namespace eVaf
</span>
213 <span class=
"hl ppc">#endif
</span> <span class=
"hl slc">// gui.h
</span><span class=
"hl ppc"></span>
216 <p>Continue implementing the
<a href=
"pswgen10.html">GUI Module
</a>.
</p>