|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the documentation of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 /*! |
|
43 \example mainwindows/application |
|
44 \title Application Example |
|
45 |
|
46 The Application example shows how to implement a standard GUI |
|
47 application with menus, toolbars, and a status bar. The example |
|
48 itself is a simple text editor program built around QPlainTextEdit. |
|
49 |
|
50 \image application.png Screenshot of the Application example |
|
51 |
|
52 Nearly all of the code for the Application example is in the \c |
|
53 MainWindow class, which inherits QMainWindow. QMainWindow |
|
54 provides the framework for windows that have menus, toolbars, |
|
55 dock windows, and a status bar. The application provides |
|
56 \menu{File}, \menu{Edit}, and \menu{Help} entries in the menu |
|
57 bar, with the following popup menus: |
|
58 |
|
59 \image application-menus.png The Application example's menu system |
|
60 |
|
61 The status bar at the bottom of the main window shows a |
|
62 description of the menu item or toolbar button under the cursor. |
|
63 |
|
64 To keep the example simple, recently opened files aren't shown in |
|
65 the \menu{File} menu, even though this feature is desired in 90% |
|
66 of applications. The \l{mainwindows/recentfiles}{Recent Files} |
|
67 example shows how to implement this. Furthermore, this example |
|
68 can only load one file at a time. The \l{mainwindows/sdi}{SDI} |
|
69 and \l{mainwindows/mdi}{MDI} examples shows how to lift these |
|
70 restrictions. |
|
71 |
|
72 \section1 MainWindow Class Definition |
|
73 |
|
74 Here's the class definition: |
|
75 |
|
76 \snippet examples/mainwindows/application/mainwindow.h 0 |
|
77 |
|
78 The public API is restricted to the constructor. In the \c |
|
79 protected section, we reimplement QWidget::closeEvent() to detect |
|
80 when the user attempts to close the window, and warn the user |
|
81 about unsaved changes. In the \c{private slots} section, we |
|
82 declare slots that correspond to menu entries, as well as a |
|
83 mysterious \c documentWasModified() slot. Finally, in the \c |
|
84 private section of the class, we have various members that will |
|
85 be explained in due time. |
|
86 |
|
87 \section1 MainWindow Class Implementation |
|
88 |
|
89 \snippet examples/mainwindows/application/mainwindow.cpp 0 |
|
90 |
|
91 We start by including \c <QtGui>, a header file that contains the |
|
92 definition of all classes in the \l QtCore and \l QtGui |
|
93 libraries. This saves us from the trouble of having to include |
|
94 every class individually. We also include \c mainwindow.h. |
|
95 |
|
96 You might wonder why we don't include \c <QtGui> in \c |
|
97 mainwindow.h and be done with it. The reason is that including |
|
98 such a large header from another header file can rapidly degrade |
|
99 performances. Here, it wouldn't do any harm, but it's still |
|
100 generally a good idea to include only the header files that are |
|
101 strictly necessary from another header file. |
|
102 |
|
103 \snippet examples/mainwindows/application/mainwindow.cpp 1 |
|
104 \snippet examples/mainwindows/application/mainwindow.cpp 2 |
|
105 |
|
106 In the constructor, we start by creating a QPlainTextEdit widget as a |
|
107 child of the main window (the \c this object). Then we call |
|
108 QMainWindow::setCentralWidget() to tell that this is going to be |
|
109 the widget that occupies the central area of the main window, |
|
110 between the toolbars and the status bar. |
|
111 |
|
112 Then we call \c createActions(), \c createMenus(), \c |
|
113 createToolBars(), and \c createStatusBar(), four private |
|
114 functions that set up the user interface. After that, we call \c |
|
115 readSettings() to restore the user's preferences. |
|
116 |
|
117 We establish a signal-slot connection between the QPlainTextEdit's |
|
118 document object and our \c documentWasModified() slot. Whenever |
|
119 the user modifies the text in the QPlainTextEdit, we want to update |
|
120 the title bar to show that the file was modified. |
|
121 |
|
122 At the end, we set the window title using the private |
|
123 \c setCurrentFile() function. We'll come back to this later. |
|
124 |
|
125 \target close event handler |
|
126 \snippet examples/mainwindows/application/mainwindow.cpp 3 |
|
127 \snippet examples/mainwindows/application/mainwindow.cpp 4 |
|
128 |
|
129 When the user attempts to close the window, we call the private |
|
130 function \c maybeSave() to give the user the possibility to save |
|
131 pending changes. The function returns true if the user wants the |
|
132 application to close; otherwise, it returns false. In the first |
|
133 case, we save the user's preferences to disk and accept the close |
|
134 event; in the second case, we ignore the close event, meaning |
|
135 that the application will stay up and running as if nothing |
|
136 happened. |
|
137 |
|
138 \snippet examples/mainwindows/application/mainwindow.cpp 5 |
|
139 \snippet examples/mainwindows/application/mainwindow.cpp 6 |
|
140 |
|
141 The \c newFile() slot is invoked when the user selects |
|
142 \menu{File|New} from the menu. We call \c maybeSave() to save any |
|
143 pending changes and if the user accepts to go on, we clear the |
|
144 QPlainTextEdit and call the private function \c setCurrentFile() to |
|
145 update the window title and clear the |
|
146 \l{QWidget::windowModified}{windowModified} flag. |
|
147 |
|
148 \snippet examples/mainwindows/application/mainwindow.cpp 7 |
|
149 \snippet examples/mainwindows/application/mainwindow.cpp 8 |
|
150 |
|
151 The \c open() slot is invoked when the user clicks |
|
152 \menu{File|Open}. We pop up a QFileDialog asking the user to |
|
153 choose a file. If the user chooses a file (i.e., \c fileName is |
|
154 not an empty string), we call the private function \c loadFile() |
|
155 to actually load the file. |
|
156 |
|
157 \snippet examples/mainwindows/application/mainwindow.cpp 9 |
|
158 \snippet examples/mainwindows/application/mainwindow.cpp 10 |
|
159 |
|
160 The \c save() slot is invoked when the user clicks |
|
161 \menu{File|Save}. If the user hasn't provided a name for the file |
|
162 yet, we call \c saveAs(); otherwise, we call the private function |
|
163 \c saveFile() to actually save the file. |
|
164 |
|
165 \snippet examples/mainwindows/application/mainwindow.cpp 11 |
|
166 \snippet examples/mainwindows/application/mainwindow.cpp 12 |
|
167 |
|
168 In \c saveAs(), we start by popping up a QFileDialog asking the |
|
169 user to provide a name. If the user clicks \gui{Cancel}, the |
|
170 returned file name is empty, and we do nothing. |
|
171 |
|
172 \snippet examples/mainwindows/application/mainwindow.cpp 13 |
|
173 \snippet examples/mainwindows/application/mainwindow.cpp 14 |
|
174 |
|
175 The application's About box is done using one statement, using |
|
176 the QMessageBox::about() static function and relying on its |
|
177 support for an HTML subset. |
|
178 |
|
179 The \l{QObject::tr()}{tr()} call around the literal string marks |
|
180 the string for translation. It is a good habit to call |
|
181 \l{QObject::tr()}{tr()} on all user-visible strings, in case you |
|
182 later decide to translate your application to other languages. |
|
183 The \l{Internationalization with Qt} overview convers |
|
184 \l{QObject::tr()}{tr()} in more detail. |
|
185 |
|
186 \snippet examples/mainwindows/application/mainwindow.cpp 15 |
|
187 \snippet examples/mainwindows/application/mainwindow.cpp 16 |
|
188 |
|
189 The \c documentWasModified() slot is invoked each time the text |
|
190 in the QPlainTextEdit changes because of user edits. We call |
|
191 QWidget::setWindowModified() to make the title bar show that the |
|
192 file was modified. How this is done varies on each platform. |
|
193 |
|
194 \snippet examples/mainwindows/application/mainwindow.cpp 17 |
|
195 \snippet examples/mainwindows/application/mainwindow.cpp 18 |
|
196 \dots |
|
197 \snippet examples/mainwindows/application/mainwindow.cpp 22 |
|
198 |
|
199 The \c createActions() private function, which is called from the |
|
200 \c MainWindow constructor, creates \l{QAction}s. The code is very |
|
201 repetitive, so we show only the actions corresponding to |
|
202 \menu{File|New}, \menu{File|Open}, and \menu{Help|About Qt}. |
|
203 |
|
204 A QAction is an object that represents one user action, such as |
|
205 saving a file or invoking a dialog. An action can be put in a |
|
206 QMenu or a QToolBar, or both, or in any other widget that |
|
207 reimplements QWidget::actionEvent(). |
|
208 |
|
209 An action has a text that is shown in the menu, an icon, a |
|
210 shortcut key, a tooltip, a status tip (shown in the status bar), |
|
211 a "What's This?" text, and more. It emits a |
|
212 \l{QAction::triggered()}{triggered()} signal whenever the user |
|
213 invokes the action (e.g., by clicking the associated menu item or |
|
214 toolbar button). We connect this signal to a slot that performs |
|
215 the actual action. |
|
216 |
|
217 The code above contains one more idiom that must be explained. |
|
218 For some of the actions, we specify an icon as a QIcon to the |
|
219 QAction constructor. The QIcon constructor takes the file name |
|
220 of an image that it tries to load. Here, the file name starts |
|
221 with \c{:}. Such file names aren't ordinary file names, but |
|
222 rather path in the executable's stored resources. We'll come back |
|
223 to this when we review the \c application.qrc file that's part of |
|
224 the project. |
|
225 |
|
226 \snippet examples/mainwindows/application/mainwindow.cpp 23 |
|
227 \snippet examples/mainwindows/application/mainwindow.cpp 24 |
|
228 |
|
229 The \gui{Edit|Cut} and \gui{Edit|Copy} actions must be available |
|
230 only when the QPlainTextEdit contains selected text. We disable them |
|
231 by default and connect the QPlainTextEdit::copyAvailable() signal to |
|
232 the QAction::setEnabled() slot, ensuring that the actions are |
|
233 disabled when the text editor has no selection. |
|
234 |
|
235 \snippet examples/mainwindows/application/mainwindow.cpp 25 |
|
236 \snippet examples/mainwindows/application/mainwindow.cpp 27 |
|
237 |
|
238 Creating actions isn't sufficient to make them available to the |
|
239 user; we must also add them to the menu system. This is what \c |
|
240 createMenus() does. We create a \menu{File}, an \menu{Edit}, and |
|
241 a \menu{Help} menu. QMainWindow::menuBar() lets us access the |
|
242 window's menu bar widget. We don't have to worry about creating |
|
243 the menu bar ourselves; the first time we call this function, the |
|
244 QMenuBar is created. |
|
245 |
|
246 Just before we create the \menu{Help} menu, we call |
|
247 QMenuBar::addSeparator(). This has no effect for most widget |
|
248 styles (e.g., Windows and Mac OS X styles), but for Motif-based |
|
249 styles this makes sure that \menu{Help} is pushed to the right |
|
250 side of the menu bar. Try running the application with various |
|
251 styles and see the results: |
|
252 |
|
253 \snippet doc/src/snippets/code/doc_src_examples_application.qdoc 0 |
|
254 |
|
255 Let's now review the toolbars: |
|
256 |
|
257 \snippet examples/mainwindows/application/mainwindow.cpp 30 |
|
258 |
|
259 Creating toolbars is very similar to creating menus. The same |
|
260 actions that we put in the menus can be reused in the toolbars. |
|
261 |
|
262 \snippet examples/mainwindows/application/mainwindow.cpp 32 |
|
263 \snippet examples/mainwindows/application/mainwindow.cpp 33 |
|
264 |
|
265 QMainWindow::statusBar() returns a pointer to the main window's |
|
266 QStatusBar widget. Like with \l{QMainWindow::menuBar()}, the |
|
267 widget is automatically created the first time the function is |
|
268 called. |
|
269 |
|
270 \snippet examples/mainwindows/application/mainwindow.cpp 34 |
|
271 \snippet examples/mainwindows/application/mainwindow.cpp 36 |
|
272 |
|
273 The \c readSettings() function is called from the constructor to |
|
274 load the user's preferences and other application settings. The |
|
275 QSettings class provides a high-level interface for storing |
|
276 settings permanently on disk. On Windows, it uses the (in)famous |
|
277 Windows registry; on Mac OS X, it uses the native XML-based |
|
278 CFPreferences API; on Unix/X11, it uses text files. |
|
279 |
|
280 The QSettings constructor takes arguments that identify your |
|
281 company and the name of the product. This ensures that the |
|
282 settings for different applications are kept separately. |
|
283 |
|
284 We use QSettings::value() to extract the value of the "pos" and |
|
285 "size" settings. The second argument to QSettings::value() is |
|
286 optional and specifies a default value for the setting if there |
|
287 exists none. This value is used the first time the application is |
|
288 run. |
|
289 |
|
290 When restoring the position and size of a window, it's important |
|
291 to call QWidget::resize() before QWidget::move(). The reason why |
|
292 is given in the \l{Window Geometry} overview. |
|
293 |
|
294 \snippet examples/mainwindows/application/mainwindow.cpp 37 |
|
295 \snippet examples/mainwindows/application/mainwindow.cpp 39 |
|
296 |
|
297 The \c writeSettings() function is called from \c closeEvent(). |
|
298 Writing settings is similar to reading them, except simpler. The |
|
299 arguments to the QSettings constructor must be the same as in \c |
|
300 readSettings(). |
|
301 |
|
302 \snippet examples/mainwindows/application/mainwindow.cpp 40 |
|
303 \snippet examples/mainwindows/application/mainwindow.cpp 41 |
|
304 |
|
305 The \c maybeSave() function is called to save pending changes. If |
|
306 there are pending changes, it pops up a QMessageBox giving the |
|
307 user to save the document. The options are QMessageBox::Yes, |
|
308 QMessageBox::No, and QMessageBox::Cancel. The \gui{Yes} button is |
|
309 made the default button (the button that is invoked when the user |
|
310 presses \key{Return}) using the QMessageBox::Default flag; the |
|
311 \gui{Cancel} button is made the escape button (the button that is |
|
312 invoked when the user presses \key{Esc}) using the |
|
313 QMessageBox::Escape flag. |
|
314 |
|
315 The \c maybeSave() function returns \c true in all cases, except |
|
316 when the user clicks \gui{Cancel}. The caller must check the |
|
317 return value and stop whatever it was doing if the return value |
|
318 is \c false. |
|
319 |
|
320 \snippet examples/mainwindows/application/mainwindow.cpp 42 |
|
321 \snippet examples/mainwindows/application/mainwindow.cpp 43 |
|
322 |
|
323 In \c loadFile(), we use QFile and QTextStream to read in the |
|
324 data. The QFile object provides access to the bytes stored in a |
|
325 file. |
|
326 |
|
327 We start by opening the file in read-only mode. The QFile::Text |
|
328 flag indicates that the file is a text file, not a binary file. |
|
329 On Unix and Mac OS X, this makes no difference, but on Windows, |
|
330 it ensures that the "\\r\\n" end-of-line sequence is converted to |
|
331 "\\n" when reading. |
|
332 |
|
333 If we successfully opened the file, we use a QTextStream object |
|
334 to read in the data. QTextStream automatically converts the 8-bit |
|
335 data into a Unicode QString and supports various encodings. If no |
|
336 encoding is specified, QTextStream assumes the file is written |
|
337 using the system's default 8-bit encoding (for example, Latin-1; |
|
338 see QTextCodec::codecForLocale() for details). |
|
339 |
|
340 Since the call to QTextStream::readAll() might take some time, we |
|
341 set the cursor to be Qt::WaitCursor for the entire application |
|
342 while it goes on. |
|
343 |
|
344 At the end, we call the private \c setCurrentFile() function, |
|
345 which we'll cover in a moment, and we display the string "File |
|
346 loaded" in the status bar for 2 seconds (2000 milliseconds). |
|
347 |
|
348 \snippet examples/mainwindows/application/mainwindow.cpp 44 |
|
349 \snippet examples/mainwindows/application/mainwindow.cpp 45 |
|
350 |
|
351 Saving a file is very similar to loading one. Here, the |
|
352 QFile::Text flag ensures that on Windows, "\\n" is converted into |
|
353 "\\r\\n" to conform to the Windows convension. |
|
354 |
|
355 \snippet examples/mainwindows/application/mainwindow.cpp 46 |
|
356 \snippet examples/mainwindows/application/mainwindow.cpp 47 |
|
357 |
|
358 The \c setCurrentFile() function is called to reset the state of |
|
359 a few variables when a file is loaded or saved, or when the user |
|
360 starts editing a new file (in which case \c fileName is empty). |
|
361 We update the \c curFile variable, clear the |
|
362 QTextDocument::modified flag and the associated \c |
|
363 QWidget:windowModified flag, and update the window title to |
|
364 contain the new file name (or \c untitled.txt). |
|
365 |
|
366 The \c strippedName() function call around \c curFile in the |
|
367 QWidget::setWindowTitle() call shortens the file name to exclude |
|
368 the path. Here's the function: |
|
369 |
|
370 \snippet examples/mainwindows/application/mainwindow.cpp 48 |
|
371 \snippet examples/mainwindows/application/mainwindow.cpp 49 |
|
372 |
|
373 \section1 The main() Function |
|
374 |
|
375 The \c main() function for this application is typical of |
|
376 applications that contain one main window: |
|
377 |
|
378 \snippet examples/mainwindows/application/main.cpp 0 |
|
379 |
|
380 \section1 The Resource File |
|
381 |
|
382 As you will probably recall, for some of the actions, we |
|
383 specified icons with file names starting with \c{:} and mentioned |
|
384 that such file names aren't ordinary file names, but path in the |
|
385 executable's stored resources. These resources are compiled |
|
386 |
|
387 The resources associated with an application are specified in a |
|
388 \c .qrc file, an XML-based file format that lists files on the |
|
389 disk. Here's the \c application.qrc file that's used by the |
|
390 Application example: |
|
391 |
|
392 \quotefile mainwindows/application/application.qrc |
|
393 |
|
394 The \c .png files listed in the \c application.qrc file are files |
|
395 that are part of the Application example's source tree. Paths are |
|
396 relative to the directory where the \c application.qrc file is |
|
397 located (the \c mainwindows/application directory). |
|
398 |
|
399 The resource file must be mentioned in the \c application.pro |
|
400 file so that \c qmake knows about it: |
|
401 |
|
402 \snippet examples/mainwindows/application/application.pro 0 |
|
403 |
|
404 \c qmake will produce make rules to generate a file called \c |
|
405 qrc_application.cpp that is linked into the application. This |
|
406 file contains all the data for the images and other resources as |
|
407 static C++ arrays of compressed binary data. See |
|
408 \l{resources.html}{The Qt Resource System} for more information |
|
409 about resources. |
|
410 */ |