summaryrefslogtreecommitdiffstats
path: root/doc/src/examples/charactermap.qdoc
blob: 64f7c0505b1d75aac4c7a9ac3f94ba594fcbd234 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file.  Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: http://www.gnu.org/copyleft/fdl.html.
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
\example widgets/charactermap
\title Character Map Example

\brief The Character Map example shows how to create a custom widget that can
both display its own content and respond to user input.

The example displays an array of characters which the user can click on
to enter text in a line edit. The contents of the line edit can then be
copied into the clipboard, and pasted into other applications. The
purpose behind this sort of tool is to allow users to enter characters
that may be unavailable or difficult to locate on their keyboards.

\image charactermap-example.png Screenshot of the Character Map example

The example consists of the following classes:

\list
\i \c CharacterWidget displays the available characters in the current
   font and style.
\i \c MainWindow provides a standard main window that contains font and
   style information, a view onto the characters, a line edit, and a push
   button for submitting text to the clipboard.
\endlist

\section1 CharacterWidget Class Definition

The \c CharacterWidget class is used to display an array of characters in
a user-specified font and style. For flexibility, we subclass QWidget and
reimplement only the functions that we need to provide basic rendering
and interaction features.

The class definition looks like this:

\snippet examples/widgets/charactermap/characterwidget.h 0

The widget does not contain any other widgets, so it must provide its own
size hint to allow its contents to be displayed correctly.
We reimplement \l{QWidget::paintEvent()} to draw custom content. We also
reimplement \l{QWidget::mousePressEvent()} to allow the user to interact
with the widget.

The updateFont() and updateStyle() slots are used to update the font and
style of the characters in the widget whenever the user changes the
settings in the application.
The class defines the characterSelected() signal so that other parts
of the application are informed whenever the user selects a character in
the widget.
As a courtesy, the widget provides a tooltip that shows the current
character value. We reimplement the \l{QWidget::mouseMoveEvent()} event
handler and define showToolTip() to enable this feature.

The \c columns, \c displayFont and \c currentKey private data members
are used to record the number of columns to be shown, the current font,
and the currently highlighted character in the widget.

\section1 CharacterWidget Class Implementation

Since the widget is to be used as a simple canvas, the constructor just
calls the base class constructor and defines some default values for
private data members.

\snippet examples/widgets/charactermap/characterwidget.cpp 0

We initialize \c currentKey with a value of -1 to indicate
that no character is initially selected. We enable mouse tracking to
allow us to follow the movement of the cursor across the widget.

The class provides two functions to allow the font and style to be set up.
Each of these modify the widget's display font and call update():

\snippet examples/widgets/charactermap/characterwidget.cpp 1
\codeline
\snippet examples/widgets/charactermap/characterwidget.cpp 2

We use a fixed size font for the display. Similarly, a fixed size hint is
provided by the sizeHint() function:

\snippet examples/widgets/charactermap/characterwidget.cpp 3

Three standard event functions are implemented so that the widget
can respond to clicks, provide tooltips, and render the available
characters. The paintEvent() shows how the contents of the widget are
arranged and displayed:

\snippet examples/widgets/charactermap/characterwidget.cpp 6

A QPainter is created for the widget and, in all cases, we ensure that the
widget's background is painted. The painter's font is set to the
user-specified display font.

The area of the widget that needs to be redrawn is used to determine which
characters need to be displayed:

\snippet examples/widgets/charactermap/characterwidget.cpp 7

Using integer division, we obtain the row and column numbers of each
characters that should be displayed, and we draw a square on the widget
for each character displayed.

\snippet examples/widgets/charactermap/characterwidget.cpp 8
\snippet examples/widgets/charactermap/characterwidget.cpp 9

The symbols for each character in the array are drawn within each square,
with the symbol for the most recently selected character displayed in red:

\snippet examples/widgets/charactermap/characterwidget.cpp 10

We do not need to take into account the difference between the area
displayed in the viewport and the area we are drawing on because
everything outside the visible area will be clipped.

The mousePressEvent() defines how the widget responds to mouse clicks.

\snippet examples/widgets/charactermap/characterwidget.cpp 5

We are only interested when the user clicks with the left mouse button
over the widget. When this happens, we calculate which character was
selected and emit the characterSelected() signal.
The character's number is found by dividing the x and y-coordinates of
the click by the size of each character's grid square. Since the number
of columns in the widget is defined by the \c columns variable, we
simply multiply the row index by that value and add the column number
to obtain the character number.

If any other mouse button is pressed, the event is passed on to the
QWidget base class. This ensures that the event can be handled properly
by any other interested widgets.

The mouseMoveEvent() maps the mouse cursor's position in global
coordinates to widget coordinates, and determines the character that
was clicked by performing the calculation

\snippet examples/widgets/charactermap/characterwidget.cpp 4

The tooltip is given a position defined in global coordinates.

\section1 MainWindow Class Definition

The \c MainWindow class provides a minimal user interface for the example,
with only a constructor, slots that respond to signals emitted by standard
widgets, and some convenience functions that are used to set up the user
interface.

The class definition looks like this:

\snippet examples/widgets/charactermap/mainwindow.h 0

The main window contains various widgets that are used to control how
the characters will be displayed, and defines the findFonts() function
for clarity and convenience. The findStyles() slot is used by the widgets
to determine the styles that are available, insertCharacter() inserts
a user-selected character into the window's line edit, and
updateClipboard() synchronizes the clipboard with the contents of the
line edit.

\section1 MainWindow Class Implementation

In the constructor, we set up the window's central widget and fill it with
some standard widgets (two comboboxes, a line edit, and a push button).
We also construct a CharacterWidget custom widget, and add a QScrollArea
so that we can view its contents:

\snippet examples/widgets/charactermap/mainwindow.cpp 0

QScrollArea provides a viewport onto the \c CharacterWidget when we set
its widget and handles much of the work needed to provide a scrolling
viewport.

The font combo box is automatically popuplated with a list of available
fonts. We list the available styles for the current font in the style
combobox using the following function:

\snippet examples/widgets/charactermap/mainwindow.cpp 1

The line edit and push button are used to supply text to the clipboard:

\snippet examples/widgets/charactermap/mainwindow.cpp 2

We also obtain a clipboard object so that we can send text entered by the
user to other applications.

Most of the signals emitted in the example come from standard widgets.
We connect these signals to slots in this class, and to the slots provided
by other widgets.

\snippet examples/widgets/charactermap/mainwindow.cpp 4

The font combobox's
\l{QFontComboBox::currentFontChanged()}{currentFontChanged()} signal is
connected to the findStyles() function so that the list of available styles
can be shown for each font that is used. Since both the font and the style
can be changed by the user, the font combobox's currentFontChanged() signal
and the style combobox's
\l{QComboBox::currentIndexChanged()}{currentIndexChanged()} are connected
directly to the character widget.

The final two connections allow characters to be selected in the character
widget, and text to be inserted into the clipboard:

\snippet examples/widgets/charactermap/mainwindow.cpp 5

The character widget emits the characterSelected() custom signal when
the user clicks on a character, and this is handled by the insertCharacter()
function in this class. The clipboard is changed when the push button emits
the clicked() signal, and we handle this with the updateClipboard() function.

The remaining code in the constructor sets up the layout of the central widget,
and provides a window title:

\snippet examples/widgets/charactermap/mainwindow.cpp 6

The font combobox is automatically populated with a list of available font
families. The styles that can be used with each font are found by the
findStyles() function. This function is called whenever the user selects a
different font in the font combobox.

\snippet examples/widgets/charactermap/mainwindow.cpp 7

We begin by recording the currently selected style, and we clear the
style combobox so that we can insert the styles associated with the
current font family.

\snippet examples/widgets/charactermap/mainwindow.cpp 8

We use the font database to collect the styles that are available for the
current font, and insert them into the style combobox. The current item is
reset if the original style is not available for this font.

The last two functions are slots that respond to signals from the character
widget and the main window's push button. The insertCharacter() function is
used to insert characters from the character widget when the user clicks a
character:

\snippet examples/widgets/charactermap/mainwindow.cpp 9

The character is inserted into the line edit at the current cursor position.

The main window's "To clipboard" push button is connected to the
updateClipboard() function so that, when it is clicked, the clipboard is
updated to contain the contents of the line edit:

\snippet examples/widgets/charactermap/mainwindow.cpp 10

We copy all the text from the line edit to the clipboard, but we do not clear
the line edit.
*/