~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to doc/html/mainwindows-application.html

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?xml version="1.0" encoding="iso-8859-1"?>
 
2
<!DOCTYPE html
 
3
    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
 
4
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 
5
<!-- /tmp/qt-4.0.0-espenr-1119621036935/qt-x11-opensource-desktop-4.0.0/doc/src/examples/application.qdoc -->
 
6
<head>
 
7
    <title>Qt 4.0: Application Example</title>
 
8
    <style>h3.fn,span.fn { margin-left: 1cm; text-indent: -1cm; }
 
9
a:link { color: #004faf; text-decoration: none }
 
10
a:visited { color: #672967; text-decoration: none }
 
11
td.postheader { font-family: sans-serif }
 
12
tr.address { font-family: sans-serif }
 
13
body { background: #ffffff; color: black; }</style>
 
14
</head>
 
15
<body>
 
16
<table border="0" cellpadding="0" cellspacing="0" width="100%">
 
17
<tr>
 
18
<td align="left" valign="top" width="32"><img src="images/qt-logo.png" align="left" width="32" height="32" border="0" /></td>
 
19
<td width="1">&nbsp;&nbsp;</td><td class="postheader" valign="center"><a href="index.html"><font color="#004faf">Home</font></a>&nbsp;&middot; <a href="classes.html"><font color="#004faf">All&nbsp;Classes</font></a>&nbsp;&middot; <a href="mainclasses.html"><font color="#004faf">Main&nbsp;Classes</font></a>&nbsp;&middot; <a href="annotated.html"><font color="#004faf">Annotated</font></a>&nbsp;&middot; <a href="groups.html"><font color="#004faf">Grouped&nbsp;Classes</font></a>&nbsp;&middot; <a href="functions.html"><font color="#004faf">Functions</font></a></td>
 
20
<td align="right" valign="top" width="230"><img src="images/trolltech-logo.png" align="right" width="203" height="32" border="0" /></td></tr></table><h1 align="center">Application Example</h1>
 
21
<p>Files:</p>
 
22
<ul>
 
23
<li><a href="mainwindows-application-mainwindow-cpp.html">mainwindows/application/mainwindow.cpp</a></li>
 
24
<li><a href="mainwindows-application-mainwindow-h.html">mainwindows/application/mainwindow.h</a></li>
 
25
<li><a href="mainwindows-application-main-cpp.html">mainwindows/application/main.cpp</a></li>
 
26
<li><a href="mainwindows-application-application-qrc.html">mainwindows/application/application.qrc</a></li>
 
27
</ul>
 
28
<p>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 <a href="qtextedit.html">QTextEdit</a>.</p>
 
29
<center><img src="images/application.png" alt="Screenshot of the Application example" /></center><p>Nearly all of the code for the Application example is in the <tt>MainWindow</tt> class, which inherits <a href="qmainwindow.html">QMainWindow</a>. <a href="qmainwindow.html">QMainWindow</a> provides the framework for windows that have menus, toolbars, dock windows, and a status bar. The application provides <b>File</b>, <b>Edit</b>, and <b>Help</b> entries in the menu bar, with the following popup menus:</p>
 
30
<center><img src="images/application-menus.png" alt="The Application example's menu system" /></center><p>The status bar at the bottom of the main window shows a description of the menu item or toolbar button under the cursor.</p>
 
31
<p>To keep the example simple, recently opened files aren't shown in the <b>File</b> menu, even though this feature is desired in 90% of applications. The <a href="mainwindows-recentfiles.html">Recent Files</a> example shows how to implement this. Furthermore, this example can only load one file at a time. The <a href="mainwindows-sdi.html">SDI</a> and <a href="mainwindows-mdi.html">MDI</a> examples shows how to lift these restrictions.</p>
 
32
<a name="mainwindow-class-definition"></a>
 
33
<h2>MainWindow Class Definition</h2>
 
34
<p>Here's the class definition:</p>
 
35
<pre>&nbsp;   class MainWindow : public QMainWindow
 
36
    {
 
37
        Q_OBJECT
 
38
 
 
39
    public:
 
40
        MainWindow();
 
41
 
 
42
    protected:
 
43
        void closeEvent(QCloseEvent *event);
 
44
 
 
45
    private slots:
 
46
        void newFile();
 
47
        void open();
 
48
        bool save();
 
49
        bool saveAs();
 
50
        void about();
 
51
        void documentWasModified();
 
52
 
 
53
    private:
 
54
        void createActions();
 
55
        void createMenus();
 
56
        void createToolBars();
 
57
        void createStatusBar();
 
58
        void readSettings();
 
59
        void writeSettings();
 
60
        bool maybeSave();
 
61
        void loadFile(const QString &amp;fileName);
 
62
        bool saveFile(const QString &amp;fileName);
 
63
        void setCurrentFile(const QString &amp;fileName);
 
64
        QString strippedName(const QString &amp;fullFileName);
 
65
 
 
66
        QTextEdit *textEdit;
 
67
        QString curFile;
 
68
 
 
69
        QMenu *fileMenu;
 
70
        QMenu *editMenu;
 
71
        QMenu *helpMenu;
 
72
        QToolBar *fileToolBar;
 
73
        QToolBar *editToolBar;
 
74
        QAction *newAct;
 
75
        QAction *openAct;
 
76
        QAction *saveAct;
 
77
        QAction *saveAsAct;
 
78
        QAction *exitAct;
 
79
        QAction *cutAct;
 
80
        QAction *copyAct;
 
81
        QAction *pasteAct;
 
82
        QAction *aboutAct;
 
83
        QAction *aboutQtAct;
 
84
    };</pre>
 
85
<p>The public API is restricted to the constructor. In the <tt>protected</tt> section, we reimplement <a href="qwidget.html#closeEvent">QWidget::closeEvent</a>() to detect when the user attempts to close the window, and warn the user about unsaved changes. In the <tt>private slots</tt> section, we declare slots that correspond to menu entries, as well as a mysterious <tt>documentWasModified()</tt> slot. Finally, in the <tt>private</tt> section of the class, we have various members that will be explained in due time.</p>
 
86
<a name="mainwindow-class-implementation"></a>
 
87
<h2>MainWindow Class Implementation</h2>
 
88
<pre>&nbsp;   #include &lt;QtGui&gt;
 
89
 
 
90
    #include &quot;mainwindow.h&quot;</pre>
 
91
<p>We start by including <tt>&lt;QtGui&gt;</tt>, a header file that contains the definition of all classes in the <a href="qtcore.html#qtcore">QtCore</a> and <a href="qtgui.html#qtgui">QtGui</a> libraries. This saves us from the trouble of having to include every class individually. We also include <tt>mainwindow.h</tt>.</p>
 
92
<p>You might wonder why we don't include <tt>&lt;QtGui&gt;</tt> in <tt>mainwindow.h</tt> 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.</p>
 
93
<pre>&nbsp;   MainWindow::MainWindow()
 
94
    {
 
95
        textEdit = new QTextEdit;
 
96
        setCentralWidget(textEdit);
 
97
 
 
98
        createActions();
 
99
        createMenus();
 
100
        createToolBars();
 
101
        createStatusBar();
 
102
 
 
103
        readSettings();
 
104
 
 
105
        connect(textEdit-&gt;document(), SIGNAL(contentsChanged()),
 
106
                this, SLOT(documentWasModified()));
 
107
 
 
108
        setWindowTitle(tr(&quot;Application&quot;));
 
109
    }</pre>
 
110
<p>In the constructor, we start by creating a <a href="qtextedit.html">QTextEdit</a> widget as a child of the main window (the <tt>this</tt> object). Then we call <a href="qmainwindow.html#setCentralWidget">QMainWindow::setCentralWidget</a>() 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.</p>
 
111
<p>Then we call <tt>createActions()</tt>, <tt>createMenus()</tt>, <tt>createToolBars()</tt>, and <tt>createStatusBar()</tt>, four private functions that set up the user interface. After that, we call <tt>readSettings()</tt> to restore the user's preferences.</p>
 
112
<p>We establish a signal-slot connection between the <a href="qtextedit.html">QTextEdit</a>'s document object and our <tt>documentWasModified()</tt> slot. Whenever the user modifies the text in the <a href="qtextedit.html">QTextEdit</a>, we want to update the title bar to show that the file was modified.</p>
 
113
<p>At the end, we set the window title to &quot;Application&quot;, the name of our program. The <a href="qobject.html#tr">tr()</a> call around the literal string marks the string for translation. It is a good habit to call <a href="qobject.html#tr">tr()</a> on all user-visible strings, in case you later decide to translate your application to other languages. The <a href="i18n.html">Internationalization with Qt</a> overview convers <a href="qobject.html#tr">tr()</a> in more detail.</p>
 
114
<a name="close-event-handler"></a><pre>&nbsp;   void MainWindow::closeEvent(QCloseEvent *event)
 
115
    {
 
116
        if (maybeSave()) {
 
117
            writeSettings();
 
118
            event-&gt;accept();
 
119
        } else {
 
120
            event-&gt;ignore();
 
121
        }
 
122
    }</pre>
 
123
<p>When the user attempts to close the window, we call the private function <tt>maybeSave()</tt> 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.</p>
 
124
<pre>&nbsp;   void MainWindow::newFile()
 
125
    {
 
126
        if (maybeSave()) {
 
127
            textEdit-&gt;clear();
 
128
            setCurrentFile(&quot;&quot;);
 
129
        }
 
130
    }</pre>
 
131
<p>The <tt>newFile()</tt> slot is invoked when the user selects <b>File|New</b> from the menu. We call <tt>maybeSave()</tt> to save any pending changes and if the user accepts to go on, we clear the <a href="qtextedit.html">QTextEdit</a> and call the private function <tt>setCurrentFile()</tt> to update the window title and clear the <a href="qwidget.html#windowModified-prop">windowModified</a> flag.</p>
 
132
<pre>&nbsp;   void MainWindow::open()
 
133
    {
 
134
        if (maybeSave()) {
 
135
            QString fileName = QFileDialog::getOpenFileName(this);
 
136
            if (!fileName.isEmpty())
 
137
                loadFile(fileName);
 
138
        }
 
139
    }</pre>
 
140
<p>The <tt>open()</tt> slot is invoked when the user clicks <b>File|Open</b>. We pop up a <a href="qfiledialog.html">QFileDialog</a> asking the user to choose a file. If the user chooses a file (i.e., <tt>fileName</tt> is not an empty string), we call the private function <tt>loadFile()</tt> to actually load the file.</p>
 
141
<pre>&nbsp;   bool MainWindow::save()
 
142
    {
 
143
        if (curFile.isEmpty()) {
 
144
            return saveAs();
 
145
        } else {
 
146
            return saveFile(curFile);
 
147
        }
 
148
    }</pre>
 
149
<p>The <tt>save()</tt> slot is invoked when the user clicks <b>File|Save</b>. If the user hasn't provided a name for the file yet, we call <tt>saveAs()</tt>; otherwise, we call the private function <tt>saveFile()</tt> to actually save the file.</p>
 
150
<pre>&nbsp;   bool MainWindow::saveAs()
 
151
    {
 
152
        QString fileName = QFileDialog::getSaveFileName(this);
 
153
        if (fileName.isEmpty())
 
154
            return false;
 
155
 
 
156
        return saveFile(fileName);
 
157
    }</pre>
 
158
<p>In <tt>saveAs()</tt>, we start by popping up a <a href="qfiledialog.html">QFileDialog</a> asking the user to provide a name. If the user clicks <b>Cancel</b>, the returned file name is empty, and we do nothing.</p>
 
159
<pre>&nbsp;   void MainWindow::about()
 
160
    {
 
161
       QMessageBox::about(this, tr(&quot;About Application&quot;),
 
162
                tr(&quot;The &lt;b&gt;Application&lt;/b&gt; example demonstrates how to &quot;
 
163
                   &quot;write modern GUI applications using Qt, with a menu bar, &quot;
 
164
                   &quot;toolbars, and a status bar.&quot;));
 
165
    }</pre>
 
166
<p>The application's About box is done using one statement, using the <a href="qmessagebox.html#about">QMessageBox::about</a>() static function and relying on its support for an HTML subset.</p>
 
167
<pre>&nbsp;   void MainWindow::documentWasModified()
 
168
    {
 
169
        setWindowModified(true);
 
170
    }</pre>
 
171
<p>The <tt>documentWasModified()</tt> slot is invoked each time the text in the <a href="qtextedit.html">QTextEdit</a> changes because of user edits. We call <a href="qwidget.html#windowModified-prop">QWidget::setWindowModified</a>() to make the title bar show that the file was modified. How this is done depends varies on the different platforms.</p>
 
172
<pre>&nbsp;   void MainWindow::createActions()
 
173
    {
 
174
        newAct = new QAction(QIcon(&quot;:/images/new.png&quot;), tr(&quot;&amp;New&quot;), this);
 
175
        newAct-&gt;setShortcut(tr(&quot;Ctrl+N&quot;));
 
176
        newAct-&gt;setStatusTip(tr(&quot;Create a new file&quot;));
 
177
        connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
 
178
 
 
179
        openAct = new QAction(QIcon(&quot;:/images/open.png&quot;), tr(&quot;&amp;Open...&quot;), this);
 
180
        openAct-&gt;setShortcut(tr(&quot;Ctrl+O&quot;));
 
181
        openAct-&gt;setStatusTip(tr(&quot;Open an existing file&quot;));
 
182
        connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
 
183
        ...
 
184
        aboutQtAct = new QAction(tr(&quot;About &amp;Qt&quot;), this);
 
185
        aboutQtAct-&gt;setStatusTip(tr(&quot;Show the Qt library's About box&quot;));
 
186
        connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
 
187
    }</pre>
 
188
<p>The <tt>createActions()</tt> private function, which is called from the <tt>MainWindow</tt> constructor, creates <a href="qaction.html">QAction</a>s. The code is very repetitive, so we show only the actions corresponding to <b>File|New</b>, <b>File|Open</b>, and <b>Help|About Qt</b>.</p>
 
189
<p>A <a href="qaction.html">QAction</a> is an object that represents one user action, such as saving a file or invoking a dialog. An action can be put in a <a href="qmenu.html">QMenu</a> or a <a href="qtoolbar.html">QToolBar</a>, or both, or in any other widget that reimplements <a href="qwidget.html#actionEvent">QWidget::actionEvent</a>().</p>
 
190
<p>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 &quot;What's This?&quot; text, and more. It emits a <a href="qaction.html#triggered">triggered()</a> 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.</p>
 
191
<p>The code above contains one more idiom that must be explained. For some of the actions, we specify an icon as a <a href="qpixmap.html">QPixmap</a> to the <a href="qaction.html">QAction</a> constructor. The <a href="qpixmap.html">QPixmap</a> constructor takes the file name of an image that it tries to load. Here, the file name starts with <tt>:</tt>. 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 <tt>application.qrc</tt> file that's part of the project.</p>
 
192
<pre>&nbsp;   void MainWindow::createMenus()
 
193
    {
 
194
        fileMenu = menuBar()-&gt;addMenu(tr(&quot;&amp;File&quot;));
 
195
        fileMenu-&gt;addAction(newAct);
 
196
        fileMenu-&gt;addAction(openAct);
 
197
        fileMenu-&gt;addAction(saveAct);
 
198
        fileMenu-&gt;addAction(saveAsAct);
 
199
        fileMenu-&gt;addSeparator();
 
200
        fileMenu-&gt;addAction(exitAct);
 
201
 
 
202
        editMenu = menuBar()-&gt;addMenu(tr(&quot;&amp;Edit&quot;));
 
203
        editMenu-&gt;addAction(cutAct);
 
204
        editMenu-&gt;addAction(copyAct);
 
205
        editMenu-&gt;addAction(pasteAct);
 
206
 
 
207
        menuBar()-&gt;addSeparator();
 
208
 
 
209
        helpMenu = menuBar()-&gt;addMenu(tr(&quot;&amp;Help&quot;));
 
210
        helpMenu-&gt;addAction(aboutAct);
 
211
        helpMenu-&gt;addAction(aboutQtAct);
 
212
    }</pre>
 
213
<p>Creating actions isn't sufficient to make them available to the user; we must also add them to the menu system. This is what <tt>createMenus()</tt> does. We create a <b>File</b>, an <b>Edit</b>, and a <b>Help</b> menu. <a href="qmainwindow.html#menuBar">QMainWindow::menuBar</a>() 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 <a href="qmenubar.html">QMenuBar</a> is created.</p>
 
214
<p>Just before we create the <b>Help</b> menu, we call <a href="qmenubar.html#addSeparator">QMenuBar::addSeparator</a>(). 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 <b>Help</b> is pushed to the right side of the menu bar. Try running the application with various styles and see the result:</p>
 
215
<pre>&nbsp;   application -style=windows
 
216
    application -style=motif
 
217
    application -style=cde</pre>
 
218
<p>Let's now review the toolbars:</p>
 
219
<pre>&nbsp;   void MainWindow::createToolBars()
 
220
    {
 
221
        fileToolBar = addToolBar(tr(&quot;File&quot;));
 
222
        fileToolBar-&gt;addAction(newAct);
 
223
        fileToolBar-&gt;addAction(openAct);
 
224
        fileToolBar-&gt;addAction(saveAct);
 
225
 
 
226
        editToolBar = addToolBar(tr(&quot;Edit&quot;));
 
227
        editToolBar-&gt;addAction(cutAct);
 
228
        editToolBar-&gt;addAction(copyAct);
 
229
        editToolBar-&gt;addAction(pasteAct);
 
230
    }</pre>
 
231
<p>Creating toolbars is very similar to creating menus. The same actions that we put in the menus can be reused in the toolbars.</p>
 
232
<pre>&nbsp;   void MainWindow::createStatusBar()
 
233
    {
 
234
        statusBar()-&gt;showMessage(tr(&quot;Ready&quot;));
 
235
    }</pre>
 
236
<p><a href="qmainwindow.html#statusBar">QMainWindow::statusBar</a>() returns a pointer to the main window's <a href="qstatusbar.html">QStatusBar</a> widget. Like with <a href="qmainwindow.html#menuBar">QMainWindow::menuBar</a>(), the widget is automatically created the first time the function is called.</p>
 
237
<pre>&nbsp;   void MainWindow::readSettings()
 
238
    {
 
239
        QSettings settings(&quot;Trolltech&quot;, &quot;Application Example&quot;);
 
240
        QPoint pos = settings.value(&quot;pos&quot;, QPoint(200, 200)).toPoint();
 
241
        QSize size = settings.value(&quot;size&quot;, QSize(400, 400)).toSize();
 
242
        resize(size);
 
243
        move(pos);
 
244
    }</pre>
 
245
<p>The <tt>readSettings()</tt> function is called from the constructor to load the user's preferences and other application settings. The <a href="qsettings.html">QSettings</a> 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/<a href="winsystem.html#x11">X11</a>, it uses text files.</p>
 
246
<p>The <a href="qsettings.html">QSettings</a> constructor takes arguments that identify your company and the name of the product. This ensures that the settings for different applications are kept separately.</p>
 
247
<p>We use <a href="qsettings.html#value">QSettings::value</a>() to extract the value of the &quot;pos&quot; and &quot;size&quot; settings. The second argument to <a href="qsettings.html#value">QSettings::value</a>() 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.</p>
 
248
<p>When restoring the position and size of a window, it's important to call <a href="qwidget.html#size-prop">QWidget::resize</a>() before <a href="qwidget.html#pos-prop">QWidget::move</a>(). The reason why is given in the <a href="geometry.html">Window Geometry</a> overview.</p>
 
249
<pre>&nbsp;   void MainWindow::writeSettings()
 
250
    {
 
251
        QSettings settings(&quot;Trolltech&quot;, &quot;Application Example&quot;);
 
252
        settings.setValue(&quot;pos&quot;, pos());
 
253
        settings.setValue(&quot;size&quot;, size());
 
254
    }</pre>
 
255
<p>The <tt>writeSettings()</tt> function is called from <tt>closeEvent()</tt>. Writing settings is similar to reading them, except simpler. The arguments to the <a href="qsettings.html">QSettings</a> constructor must be the same as in <tt>readSettings()</tt>.</p>
 
256
<pre>&nbsp;   bool MainWindow::maybeSave()
 
257
    {
 
258
        if (textEdit-&gt;document()-&gt;isModified()) {
 
259
            int ret = QMessageBox::warning(this, tr(&quot;Application&quot;),
 
260
                         tr(&quot;The document has been modified.\n&quot;
 
261
                            &quot;Do you want to save your changes?&quot;),
 
262
                         QMessageBox::Yes | QMessageBox::Default,
 
263
                         QMessageBox::No,
 
264
                         QMessageBox::Cancel | QMessageBox::Escape);
 
265
            if (ret == QMessageBox::Yes)
 
266
                return save();
 
267
            else if (ret == QMessageBox::Cancel)
 
268
                return false;
 
269
        }
 
270
        return true;
 
271
    }</pre>
 
272
<p>The <tt>maybeSave()</tt> function is called to save pending changes. If there are pending changes, it pops up a <a href="qmessagebox.html">QMessageBox</a> giving the user to save the document. The options are <a href="qmessagebox.html#Button-enum">QMessageBox::Yes</a>, <a href="qmessagebox.html#Button-enum">QMessageBox::No</a>, and <a href="qmessagebox.html#Button-enum">QMessageBox::Cancel</a>. The <b>Yes</b> button is made the default button (the button that is invoked when the user presses <b>Return</b>) using the <a href="qmessagebox.html#Button-enum">QMessageBox::Default</a> flag; the <b>Cancel</b> button is made the escape button (the button that is invoked when the user presses <b>Esc</b>) using the <a href="qmessagebox.html#Button-enum">QMessageBox::Escape</a> flag.</p>
 
273
<p>The <tt>maybeSave()</tt> function returns <tt>true</tt> in all cases, except when the user clicks <b>Cancel</b>. The caller must check the return value and stop whatever it was doing if the return value is <tt>false</tt>.</p>
 
274
<pre>&nbsp;   void MainWindow::loadFile(const QString &amp;fileName)
 
275
    {
 
276
        QFile file(fileName);
 
277
        if (!file.open(QFile::ReadOnly | QFile::Text)) {
 
278
            QMessageBox::warning(this, tr(&quot;Application&quot;),
 
279
                                 tr(&quot;Cannot read file %1:\n%2.&quot;)
 
280
                                 .arg(fileName)
 
281
                                 .arg(file.errorString()));
 
282
            return;
 
283
        }
 
284
 
 
285
        QTextStream in(&amp;file);
 
286
        QApplication::setOverrideCursor(Qt::WaitCursor);
 
287
        textEdit-&gt;setPlainText(in.readAll());
 
288
        QApplication::restoreOverrideCursor();
 
289
 
 
290
        setCurrentFile(fileName);
 
291
        statusBar()-&gt;showMessage(tr(&quot;File loaded&quot;), 2000);
 
292
    }</pre>
 
293
<p>In <tt>loadFile()</tt>, we use <a href="qfile.html">QFile</a> and <a href="qtextstream.html">QTextStream</a> to read in the data. The <a href="qfile.html">QFile</a> object provides access to the bytes stored in a file.</p>
 
294
<p>We start by opening the file in read-only mode. The <a href="qiodevice.html#OpenModeFlag-enum">QFile::Text</a> 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 &quot;\r\n&quot; end-of-line sequence is converted to &quot;\n&quot; when reading.</p>
 
295
<p>If we successfully opened the file, we use a <a href="qtextstream.html">QTextStream</a> object to read in the data. <a href="qtextstream.html">QTextStream</a> automatically converts the 8-bit data into a Unicode <a href="qstring.html">QString</a> and supports various encodings. If no encoding is specified, <a href="qtextstream.html">QTextStream</a> assumes the file is written using the system's default 8-bit encoding (for example, Latin-1; see <a href="qtextcodec.html#codecForLocale">QTextCodec::codecForLocale</a>() for details).</p>
 
296
<p>Since the call to <a href="qtextstream.html#readAll">QTextStream::readAll</a>() might take some time, we set the cursor to be <a href="qt.html#CursorShape-enum">Qt::WaitCursor</a> for the entire application while it goes on.</p>
 
297
<p>At the end, we call the private <tt>setCurrentFile()</tt> function, which we'll cover in a moment, and we display the string &quot;File loaded&quot; in the status bar for 2 seconds (2000 milliseconds).</p>
 
298
<pre>&nbsp;   bool MainWindow::saveFile(const QString &amp;fileName)
 
299
    {
 
300
        QFile file(fileName);
 
301
        if (!file.open(QFile::WriteOnly | QFile::Text)) {
 
302
            QMessageBox::warning(this, tr(&quot;Application&quot;),
 
303
                                 tr(&quot;Cannot write file %1:\n%2.&quot;)
 
304
                                 .arg(fileName)
 
305
                                 .arg(file.errorString()));
 
306
            return false;
 
307
        }
 
308
 
 
309
        QTextStream out(&amp;file);
 
310
        QApplication::setOverrideCursor(Qt::WaitCursor);
 
311
        out &lt;&lt; textEdit-&gt;toPlainText();
 
312
        QApplication::restoreOverrideCursor();
 
313
 
 
314
        setCurrentFile(fileName);
 
315
        statusBar()-&gt;showMessage(tr(&quot;File saved&quot;), 2000);
 
316
        return true;
 
317
    }</pre>
 
318
<p>Saving a file is very similar to loading one. Here, the <a href="qiodevice.html#OpenModeFlag-enum">QFile::Text</a> flag ensures that on Windows, &quot;\n&quot; is converted into &quot;\r\n&quot; to conform to the Windows convension.</p>
 
319
<pre>&nbsp;   void MainWindow::setCurrentFile(const QString &amp;fileName)
 
320
    {
 
321
        curFile = fileName;
 
322
        textEdit-&gt;document()-&gt;setModified(false);
 
323
        setWindowModified(false);
 
324
 
 
325
        if (curFile.isEmpty())
 
326
            setWindowTitle(tr(&quot;Application&quot;));
 
327
        else
 
328
            setWindowTitle(tr(&quot;%1[*] - %2&quot;).arg(strippedName(curFile))
 
329
                                           .arg(tr(&quot;Application&quot;)));
 
330
    }</pre>
 
331
<p>The <tt>setCurrentFile()</tt> 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 <tt>fileName</tt> is empty). We update the <tt>curFile</tt> variable, clear the <a href="qtextdocument.html#modified-prop">QTextDocument::modified</a> flag and the associated <tt>QWidget:windowModified</tt> flag, and update the window title to contain the new file name.</p>
 
332
<p>The <tt>strippedName()</tt> function call around <tt>curFile</tt> in the <a href="qwidget.html#windowTitle-prop">QWidget::setWindowTitle</a>() call shortens the file name to exclude the path. Here's the function:</p>
 
333
<pre>&nbsp;   QString MainWindow::strippedName(const QString &amp;fullFileName)
 
334
    {
 
335
        return QFileInfo(fullFileName).fileName();
 
336
    }</pre>
 
337
<a name="the-main-function"></a>
 
338
<h2>The main() Function</h2>
 
339
<p>The <tt>main()</tt> function for this application is typical of applications that contain one main window:</p>
 
340
<pre>&nbsp;   #include &lt;QApplication&gt;
 
341
 
 
342
    #include &quot;mainwindow.h&quot;
 
343
 
 
344
    int main(int argc, char *argv[])
 
345
    {
 
346
        Q_INIT_RESOURCE(application);
 
347
 
 
348
        QApplication app(argc, argv);
 
349
        MainWindow mainWin;
 
350
        mainWin.show();
 
351
        return app.exec();
 
352
    }</pre>
 
353
<a name="the-resource-file"></a>
 
354
<h2>The Resource File</h2>
 
355
<p>As you will probably recall, for some of the actions, we specified icons with file names starting with <tt>:</tt> and mentioned that such file names aren't ordinary file names, but path in the executable's stored resources. These resources are compiled</p>
 
356
<p>The resources associated with an application are specified in a <tt>.qrc</tt> file, an XML-based file format that lists files on the disk. Here's the <tt>application.qrc</tt> file that's used by the Application example:</p>
 
357
<pre>&nbsp;   &lt;!DOCTYPE RCC&gt;&lt;RCC version=&quot;1.0&quot;&gt;
 
358
    &lt;qresource&gt;
 
359
        &lt;file&gt;images/copy.png&lt;/file&gt;
 
360
        &lt;file&gt;images/cut.png&lt;/file&gt;
 
361
        &lt;file&gt;images/new.png&lt;/file&gt;
 
362
        &lt;file&gt;images/open.png&lt;/file&gt;
 
363
        &lt;file&gt;images/paste.png&lt;/file&gt;
 
364
        &lt;file&gt;images/save.png&lt;/file&gt;
 
365
    &lt;/qresource&gt;
 
366
    &lt;/RCC&gt;</pre>
 
367
<p>The <tt>.png</tt> files listed in the <tt>application.qrc</tt> file are files that are part of the Application example's source tree. Paths are relative to the directory where the <tt>application.qrc</tt> file is located (the <tt>mainwindows/application</tt> directory).</p>
 
368
<p>The resource file must be mentioned in the <tt>application.pro</tt> file so that <tt>qmake</tt> knows about it:</p>
 
369
<pre>&nbsp;   RESOURCES     = application.qrc</pre>
 
370
<p><tt>qmake</tt> will produce make rules to generate a file called <tt>qrc_application.cpp</tt> 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 <a href="resources.html">The Qt Resource System</a> for more information about resources.</p>
 
371
<p /><address><hr /><div align="center">
 
372
<table width="100%" cellspacing="0" border="0"><tr class="address">
 
373
<td width="30%">Copyright &copy; 2005 <a href="trolltech.html">Trolltech</a></td>
 
374
<td width="40%" align="center"><a href="trademarks.html">Trademarks</a></td>
 
375
<td width="30%" align="right"><div align="right">Qt 4.0.0</div></td>
 
376
</tr></table></div></address></body>
 
377
</html>