1ed8251667
\menu command has been replaced by \uicontrol in qdoc Change-Id: Ib105df58c565c96b34579720acb62fe64e7806c4 Reviewed-by: Casper van Donderen <casper.vandonderen@nokia.com>
401 lines
17 KiB
Plaintext
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.
|
|
*/
|