| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** 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 The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/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: https://www.gnu.org/licenses/fdl-1.3.html. |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| /*! |
| \example mainwindows/application |
| \title Application Example |
| \ingroup examples-mainwindow |
| |
| \brief 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. Furthermore, this example can only load one file at a |
| time. The \l{mainwindows/sdi}{SDI} and \l{mainwindows/mdi}{MDI} examples |
| show how to lift these restrictions and how to implement recently opened files |
| handling. |
| |
| \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 <QtWidgets>, a header file that contains the |
| definition of all classes in the Qt Core, Qt GUI and Qt Widgets |
| modules. 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 <QtWidgets> 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() and \c createStatusBar(), two 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 and populates |
| the menus and two toolbars. 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). |
| |
| Instances of QAction can be created by passing a parent QObject or |
| by using one of the convenience functions of QMenu, QMenuBar or QToolBar. |
| We create the actions that are in a menu as well as in a toolbar |
| parented on the window to prevent ownership issues. For actions |
| that are only in the menu, we use the convenience function |
| QMenu::addAction(), which allows us to pass text, icon and the |
| target object and its slot member function. |
| |
| Creating toolbars is very similar to creating menus. The same |
| actions that we put in the menus can be reused in the toolbars. |
| After creating the action, we add it to the toolbar using |
| QToolBar::addAction(). |
| |
| 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. We use QIcon::fromTheme() to obtain |
| the correct standard icon from the underlying window system. |
| If that fails due to the platform not supporting it, we |
| pass a file name as fallback. 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. |
| |
| Just before we create the \uicontrol{Help} menu, we call |
| QMenuBar::addSeparator(). This has no effect for most widget |
| styles (e.g., Windows and \macos styles), but for some |
| styles this makes sure that \uicontrol{Help} is pushed to the right |
| side of the menu bar. |
| |
| \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 \macos, 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 geometry setting. |
| 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. |
| |
| We use QWidget::saveGeometry() and Widget::restoreGeometry() to |
| save the position. They use an opaque QByteArray to store |
| screen number, geometry and window state. |
| |
| \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} or saving the file fails. |
| 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 \macos, 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 similar to loading one. We use QSaveFile to ensure |
| all data are safely written and existing files are not damaged |
| should writing fail. |
| We use the QFile::Text flag to make sure that on Windows, "\\n" |
| is converted into "\\r\\n" to conform to the Windows convention. |
| |
| |
| \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 |
| |
| The main function uses QCommandLineParser to check whether some file |
| argument was passed to the application and loads it via |
| MainWindow::loadFile(). |
| |
| \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. |
| */ |