summaryrefslogtreecommitdiffstats
path: root/doc/src/examples/application.qdoc
blob: 0dad46ba4b596884487b1768b63ca510c8544a17 (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
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights.  These rights are described in the Nokia Qt LGPL
** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
    \example mainwindows/application
    \title Application Example

    The Application example shows how to implement a standard GUI
    application with menus, toolbars, and a status bar. The example
    itself is a simple text editor program built around QTextEdit.

    \image application.png Screenshot of the Application example

    Nearly all of the code for the Application example is in the \c
    MainWindow class, which inherits QMainWindow. QMainWindow
    provides the framework for windows that have menus, toolbars,
    dock windows, and a status bar. The application provides
    \menu{File}, \menu{Edit}, and \menu{Help} entries in the menu
    bar, with the following popup menus:

    \image application-menus.png The Application example's menu system

    The status bar at the bottom of the main window shows a
    description of the menu item or toolbar button under the cursor.

    To keep the example simple, recently opened files aren't shown in
    the \menu{File} menu, even though this feature is desired in 90%
    of applications. The \l{mainwindows/recentfiles}{Recent Files}
    example shows how to implement this. Furthermore, this example
    can only load one file at a time. The \l{mainwindows/sdi}{SDI}
    and \l{mainwindows/mdi}{MDI} examples shows how to lift these
    restrictions.

    \section1 MainWindow Class Definition

    Here's the class definition:

    \snippet examples/mainwindows/application/mainwindow.h 0

    The public API is restricted to the constructor. In the \c
    protected section, we reimplement QWidget::closeEvent() to detect
    when the user attempts to close the window, and warn the user
    about unsaved changes. In the \c{private slots} section, we
    declare slots that correspond to menu entries, as well as a
    mysterious \c documentWasModified() slot. Finally, in the \c
    private section of the class, we have various members that will
    be explained in due time.

    \section1 MainWindow Class Implementation

    \snippet examples/mainwindows/application/mainwindow.cpp 0

    We start by including \c <QtGui>, a header file that contains the
    definition of all classes in the \l QtCore and \l QtGui
    libraries. This saves us from the trouble of having to include
    every class individually. We also include \c mainwindow.h.

    You might wonder why we don't include \c <QtGui> in \c
    mainwindow.h and be done with it. The reason is that including
    such a large header from another header file can rapidly degrade
    performances. Here, it wouldn't do any harm, but it's still
    generally a good idea to include only the header files that are
    strictly necessary from another header file.

    \snippet examples/mainwindows/application/mainwindow.cpp 1
    \snippet examples/mainwindows/application/mainwindow.cpp 2

    In the constructor, we start by creating a QTextEdit widget as a
    child of the main window (the \c this object). Then we call
    QMainWindow::setCentralWidget() to tell that this is going to be
    the widget that occupies the central area of the main window,
    between the toolbars and the status bar.

    Then we call \c createActions(), \c createMenus(), \c
    createToolBars(), and \c createStatusBar(), four private
    functions that set up the user interface. After that, we call \c
    readSettings() to restore the user's preferences.

    We establish a signal-slot connection between the QTextEdit's
    document object and our \c documentWasModified() slot. Whenever
    the user modifies the text in the QTextEdit, we want to update
    the title bar to show that the file was modified.

    At the end, we set the window title using the private
    \c setCurrentFile() function. We'll come back to this later.

    \target close event handler
    \snippet examples/mainwindows/application/mainwindow.cpp 3
    \snippet examples/mainwindows/application/mainwindow.cpp 4

    When the user attempts to close the window, we call the private
    function \c maybeSave() to give the user the possibility to save
    pending changes. The function returns true if the user wants the
    application to close; otherwise, it returns false. In the first
    case, we save the user's preferences to disk and accept the close
    event; in the second case, we ignore the close event, meaning
    that the application will stay up and running as if nothing
    happened.

    \snippet examples/mainwindows/application/mainwindow.cpp 5
    \snippet examples/mainwindows/application/mainwindow.cpp 6

    The \c newFile() slot is invoked when the user selects
    \menu{File|New} from the menu. We call \c maybeSave() to save any
    pending changes and if the user accepts to go on, we clear the
    QTextEdit and call the private function \c setCurrentFile() to
    update the window title and clear the
    \l{QWidget::windowModified}{windowModified} flag.

    \snippet examples/mainwindows/application/mainwindow.cpp 7
    \snippet examples/mainwindows/application/mainwindow.cpp 8

    The \c open() slot is invoked when the user clicks
    \menu{File|Open}. We pop up a QFileDialog asking the user to
    choose a file. If the user chooses a file (i.e., \c fileName is
    not an empty string), we call the private function \c loadFile()
    to actually load the file.

    \snippet examples/mainwindows/application/mainwindow.cpp 9
    \snippet examples/mainwindows/application/mainwindow.cpp 10

    The \c save() slot is invoked when the user clicks
    \menu{File|Save}. If the user hasn't provided a name for the file
    yet, we call \c saveAs(); otherwise, we call the private function
    \c saveFile() to actually save the file.

    \snippet examples/mainwindows/application/mainwindow.cpp 11
    \snippet examples/mainwindows/application/mainwindow.cpp 12

    In \c saveAs(), we start by popping up a QFileDialog asking the
    user to provide a name. If the user clicks \gui{Cancel}, the
    returned file name is empty, and we do nothing.

    \snippet examples/mainwindows/application/mainwindow.cpp 13
    \snippet examples/mainwindows/application/mainwindow.cpp 14

    The application's About box is done using one statement, using
    the QMessageBox::about() static function and relying on its
    support for an HTML subset.

    The \l{QObject::tr()}{tr()} call around the literal string marks
    the string for translation. It is a good habit to call
    \l{QObject::tr()}{tr()} on all user-visible strings, in case you
    later decide to translate your application to other languages.
    The \l{Internationalization with Qt} overview convers
    \l{QObject::tr()}{tr()} in more detail.

    \snippet examples/mainwindows/application/mainwindow.cpp 15
    \snippet examples/mainwindows/application/mainwindow.cpp 16

    The \c documentWasModified() slot is invoked each time the text
    in the QTextEdit changes because of user edits. We call
    QWidget::setWindowModified() to make the title bar show that the
    file was modified. How this is done varies on each platform.

    \snippet examples/mainwindows/application/mainwindow.cpp 17
    \snippet examples/mainwindows/application/mainwindow.cpp 18
    \dots
    \snippet examples/mainwindows/application/mainwindow.cpp 22

    The \c createActions() private function, which is called from the
    \c MainWindow constructor, creates \l{QAction}s. The code is very
    repetitive, so we show only the actions corresponding to
    \menu{File|New}, \menu{File|Open}, and \menu{Help|About Qt}.

    A QAction is an object that represents one user action, such as
    saving a file or invoking a dialog. An action can be put in a
    QMenu or a QToolBar, or both, or in any other widget that
    reimplements QWidget::actionEvent().

    An action has a text that is shown in the menu, an icon, a
    shortcut key, a tooltip, a status tip (shown in the status bar),
    a "What's This?" text, and more. It emits a
    \l{QAction::triggered()}{triggered()} signal whenever the user
    invokes the action (e.g., by clicking the associated menu item or
    toolbar button). We connect this signal to a slot that performs
    the actual action.

    The code above contains one more idiom that must be explained.
    For some of the actions, we specify an icon as a QIcon to the
    QAction constructor. The QIcon constructor takes the file name
    of an image that it tries to load. Here, the file name starts
    with \c{:}. Such file names aren't ordinary file names, but
    rather path in the executable's stored resources. We'll come back
    to this when we review the \c application.qrc file that's part of
    the project.

    \snippet examples/mainwindows/application/mainwindow.cpp 23
    \snippet examples/mainwindows/application/mainwindow.cpp 24

    The \gui{Edit|Cut} and \gui{Edit|Copy} actions must be available
    only when the QTextEdit contains selected text. We disable them
    by default and connect the QTextEdit::copyAvailable() signal to
    the QAction::setEnabled() slot, ensuring that the actions are
    disabled when the text editor has no selection.

    \snippet examples/mainwindows/application/mainwindow.cpp 25
    \snippet examples/mainwindows/application/mainwindow.cpp 27

    Creating actions isn't sufficient to make them available to the
    user; we must also add them to the menu system. This is what \c
    createMenus() does. We create a \menu{File}, an \menu{Edit}, and
    a \menu{Help} menu. QMainWindow::menuBar() lets us access the
    window's menu bar widget. We don't have to worry about creating
    the menu bar ourselves; the first time we call this function, the
    QMenuBar is created.

    Just before we create the \menu{Help} menu, we call
    QMenuBar::addSeparator(). This has no effect for most widget
    styles (e.g., Windows and Mac OS X styles), but for Motif-based
    styles this makes sure that \menu{Help} is pushed to the right
    side of the menu bar. Try running the application with various
    styles and see the results:

    \snippet doc/src/snippets/code/doc_src_examples_application.qdoc 0

    Let's now review the toolbars:

    \snippet examples/mainwindows/application/mainwindow.cpp 30

    Creating toolbars is very similar to creating menus. The same
    actions that we put in the menus can be reused in the toolbars.

    \snippet examples/mainwindows/application/mainwindow.cpp 32
    \snippet examples/mainwindows/application/mainwindow.cpp 33

    QMainWindow::statusBar() returns a pointer to the main window's
    QStatusBar widget. Like with \l{QMainWindow::menuBar()}, the
    widget is automatically created the first time the function is
    called.

    \snippet examples/mainwindows/application/mainwindow.cpp 34
    \snippet examples/mainwindows/application/mainwindow.cpp 36

    The \c readSettings() function is called from the constructor to
    load the user's preferences and other application settings. The
    QSettings class provides a high-level interface for storing
    settings permanently on disk. On Windows, it uses the (in)famous
    Windows registry; on Mac OS X, it uses the native XML-based
    CFPreferences API; on Unix/X11, it uses text files.

    The QSettings constructor takes arguments that identify your
    company and the name of the product. This ensures that the
    settings for different applications are kept separately.

    We use QSettings::value() to extract the value of the "pos" and
    "size" settings. The second argument to QSettings::value() is
    optional and specifies a default value for the setting if there
    exists none. This value is used the first time the application is
    run.

    When restoring the position and size of a window, it's important
    to call QWidget::resize() before QWidget::move(). The reason why
    is given in the \l{geometry.html}{Window Geometry} overview.

    \snippet examples/mainwindows/application/mainwindow.cpp 37
    \snippet examples/mainwindows/application/mainwindow.cpp 39

    The \c writeSettings() function is called from \c closeEvent().
    Writing settings is similar to reading them, except simpler. The
    arguments to the QSettings constructor must be the same as in \c
    readSettings().

    \snippet examples/mainwindows/application/mainwindow.cpp 40
    \snippet examples/mainwindows/application/mainwindow.cpp 41

    The \c maybeSave() function is called to save pending changes. If
    there are pending changes, it pops up a QMessageBox giving the
    user to save the document. The options are QMessageBox::Yes,
    QMessageBox::No, and QMessageBox::Cancel. The \gui{Yes} button is
    made the default button (the button that is invoked when the user
    presses \key{Return}) using the QMessageBox::Default flag; the
    \gui{Cancel} button is made the escape button (the button that is
    invoked when the user presses \key{Esc}) using the
    QMessageBox::Escape flag.

    The \c maybeSave() function returns \c true in all cases, except
    when the user clicks \gui{Cancel}. The caller must check the
    return value and stop whatever it was doing if the return value
    is \c false.

    \snippet examples/mainwindows/application/mainwindow.cpp 42
    \snippet examples/mainwindows/application/mainwindow.cpp 43

    In \c loadFile(), we use QFile and QTextStream to read in the
    data. The QFile object provides access to the bytes stored in a
    file.

    We start by opening the file in read-only mode. The QFile::Text
    flag indicates that the file is a text file, not a binary file.
    On Unix and Mac OS X, this makes no difference, but on Windows,
    it ensures that the "\\r\\n" end-of-line sequence is converted to
    "\\n" when reading.

    If we successfully opened the file, we use a QTextStream object
    to read in the data. QTextStream automatically converts the 8-bit
    data into a Unicode QString and supports various encodings. If no
    encoding is specified, QTextStream assumes the file is written
    using the system's default 8-bit encoding (for example, Latin-1;
    see QTextCodec::codecForLocale() for details).

    Since the call to QTextStream::readAll() might take some time, we
    set the cursor to be Qt::WaitCursor for the entire application
    while it goes on.

    At the end, we call the private \c setCurrentFile() function,
    which we'll cover in a moment, and we display the string "File
    loaded" in the status bar for 2 seconds (2000 milliseconds).

    \snippet examples/mainwindows/application/mainwindow.cpp 44
    \snippet examples/mainwindows/application/mainwindow.cpp 45

    Saving a file is very similar to loading one. Here, the
    QFile::Text flag ensures that on Windows, "\\n" is converted into
    "\\r\\n" to conform to the Windows convension.

    \snippet examples/mainwindows/application/mainwindow.cpp 46
    \snippet examples/mainwindows/application/mainwindow.cpp 47

    The \c setCurrentFile() function is called to reset the state of
    a few variables when a file is loaded or saved, or when the user
    starts editing a new file (in which case \c fileName is empty).
    We update the \c curFile variable, clear the
    QTextDocument::modified flag and the associated \c
    QWidget:windowModified flag, and update the window title to
    contain the new file name (or \c untitled.txt).

    The \c strippedName() function call around \c curFile in the
    QWidget::setWindowTitle() call shortens the file name to exclude
    the path. Here's the function:

    \snippet examples/mainwindows/application/mainwindow.cpp 48
    \snippet examples/mainwindows/application/mainwindow.cpp 49

    \section1 The main() Function

    The \c main() function for this application is typical of
    applications that contain one main window:

    \snippet examples/mainwindows/application/main.cpp 0

    \section1 The Resource File

    As you will probably recall, for some of the actions, we
    specified icons with file names starting with \c{:} and mentioned
    that such file names aren't ordinary file names, but path in the
    executable's stored resources. These resources are compiled

    The resources associated with an application are specified in a
    \c .qrc file, an XML-based file format that lists files on the
    disk. Here's the \c application.qrc file that's used by the
    Application example:

    \quotefile mainwindows/application/application.qrc

    The \c .png files listed in the \c application.qrc file are files
    that are part of the Application example's source tree. Paths are
    relative to the directory where the \c application.qrc file is
    located (the \c mainwindows/application directory).

    The resource file must be mentioned in the \c application.pro
    file  so that \c qmake knows about it:

    \snippet examples/mainwindows/application/application.pro 0

    \c qmake will produce make rules to generate a file called \c
    qrc_application.cpp that is linked into the application. This
    file contains all the data for the images and other resources as
    static C++ arrays of compressed binary data. See
    \l{resources.html}{The Qt Resource System} for more information
    about resources.
*/