qt5base-lts/examples/widgets/doc/application.qdoc
Andy Nichols 1ed8251667 Doc: change \menu to \uicontrol in application example docs
\menu command has been replaced by \uicontrol in qdoc

Change-Id: Ib105df58c565c96b34579720acb62fe64e7806c4
Reviewed-by: Casper van Donderen <casper.vandonderen@nokia.com>
2012-08-22 09:08:02 +02:00

401 lines
17 KiB
Plaintext

/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** GNU Free Documentation License
** 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms
** and conditions contained in a signed written agreement between you
** and Nokia.
**
**
**
**
**
** $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 QPlainTextEdit.
\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
\uicontrol{File}, \uicontrol{Edit}, and \uicontrol{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 \uicontrol{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 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 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 mainwindows/application/mainwindow.cpp 1
\snippet mainwindows/application/mainwindow.cpp 2
In the constructor, we start by creating a QPlainTextEdit 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 QPlainTextEdit's
document object and our \c documentWasModified() slot. Whenever
the user modifies the text in the QPlainTextEdit, 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 mainwindows/application/mainwindow.cpp 3
\snippet 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 mainwindows/application/mainwindow.cpp 5
\snippet mainwindows/application/mainwindow.cpp 6
The \c newFile() slot is invoked when the user selects
\uicontrol{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
QPlainTextEdit and call the private function \c setCurrentFile() to
update the window title and clear the
\l{QWidget::windowModified}{windowModified} flag.
\snippet mainwindows/application/mainwindow.cpp 7
\snippet mainwindows/application/mainwindow.cpp 8
The \c open() slot is invoked when the user clicks
\uicontrol{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 mainwindows/application/mainwindow.cpp 9
\snippet mainwindows/application/mainwindow.cpp 10
The \c save() slot is invoked when the user clicks
\uicontrol{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 mainwindows/application/mainwindow.cpp 11
\snippet 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 \uicontrol{Cancel}, the
returned file name is empty, and we do nothing.
\snippet mainwindows/application/mainwindow.cpp 13
\snippet 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 covers
\l{QObject::tr()}{tr()} in more detail.
\snippet mainwindows/application/mainwindow.cpp 15
\snippet mainwindows/application/mainwindow.cpp 16
The \c documentWasModified() slot is invoked each time the text
in the QPlainTextEdit 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 mainwindows/application/mainwindow.cpp 17
\snippet mainwindows/application/mainwindow.cpp 18
\dots
\snippet 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
\uicontrol{File|New}, \uicontrol{File|Open}, and \uicontrol{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 mainwindows/application/mainwindow.cpp 23
\snippet mainwindows/application/mainwindow.cpp 24
The \uicontrol{Edit|Cut} and \uicontrol{Edit|Copy} actions must be available
only when the QPlainTextEdit contains selected text. We disable them
by default and connect the QPlainTextEdit::copyAvailable() signal to
the QAction::setEnabled() slot, ensuring that the actions are
disabled when the text editor has no selection.
\snippet mainwindows/application/mainwindow.cpp 25
\snippet 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 \uicontrol{File}, an \uicontrol{Edit}, and
a \uicontrol{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 \uicontrol{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 \uicontrol{Help} is pushed to the right
side of the menu bar. Try running the application with various
styles and see the results:
\code
application -style=windows
application -style=motif
application -style=cde
\endcode
Let's now review the toolbars:
\snippet 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 mainwindows/application/mainwindow.cpp 32
\snippet 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 mainwindows/application/mainwindow.cpp 34
\snippet 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{Window Geometry} overview.
\snippet mainwindows/application/mainwindow.cpp 37
\snippet 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 mainwindows/application/mainwindow.cpp 40
\snippet 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 \uicontrol{Yes} button is
made the default button (the button that is invoked when the user
presses \uicontrol{Return}) using the QMessageBox::Default flag; the
\uicontrol{Cancel} button is made the escape button (the button that is
invoked when the user presses \uicontrol{Esc}) using the
QMessageBox::Escape flag.
The \c maybeSave() function returns \c true in all cases, except
when the user clicks \uicontrol{Cancel}. The caller must check the
return value and stop whatever it was doing if the return value
is \c false.
\snippet mainwindows/application/mainwindow.cpp 42
\snippet 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 mainwindows/application/mainwindow.cpp 44
\snippet 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 mainwindows/application/mainwindow.cpp 46
\snippet 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 mainwindows/application/mainwindow.cpp 48
\snippet 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 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 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.
*/