1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include <QtWidgets>
52
53#include "mainwindow.h"
54#include "scribblearea.h"
55
56//! [0]
57MainWindow::MainWindow()
58{
59 scribbleArea = new ScribbleArea;
60 setCentralWidget(scribbleArea);
61
62 createActions();
63 createMenus();
64
65 setWindowTitle(tr("Finger Paint"));
66 resize(500, 500);
67}
68//! [0]
69
70//! [1]
71void MainWindow::closeEvent(QCloseEvent *event)
72//! [1] //! [2]
73{
74 if (maybeSave()) {
75 event->accept();
76 } else {
77 event->ignore();
78 }
79}
80//! [2]
81
82//! [3]
83void MainWindow::open()
84//! [3] //! [4]
85{
86 if (maybeSave()) {
87 QString fileName = QFileDialog::getOpenFileName(this,
88 tr("Open File"), QDir::currentPath());
89 if (!fileName.isEmpty())
90 scribbleArea->openImage(fileName);
91 }
92}
93//! [4]
94
95//! [5]
96void MainWindow::save()
97//! [5] //! [6]
98{
99 QAction *action = qobject_cast<QAction *>(sender());
100 QByteArray fileFormat = action->data().toByteArray();
101 saveFile(fileFormat);
102}
103//! [6]
104
105//! [11]
106void MainWindow::about()
107//! [11] //! [12]
108{
109 QMessageBox::about(this, tr("About Scribble"),
110 tr("<p>The <b>Scribble</b> example shows how to use QMainWindow as the "
111 "base widget for an application, and how to reimplement some of "
112 "QWidget's event handlers to receive the events generated for "
113 "the application's widgets:</p><p> We reimplement the mouse event "
114 "handlers to facilitate drawing, the paint event handler to "
115 "update the application and the resize event handler to optimize "
116 "the application's appearance. In addition we reimplement the "
117 "close event handler to intercept the close events before "
118 "terminating the application.</p><p> The example also demonstrates "
119 "how to use QPainter to draw an image in real time, as well as "
120 "to repaint widgets.</p>"));
121}
122//! [12]
123
124//! [13]
125void MainWindow::createActions()
126//! [13] //! [14]
127{
128 openAct = new QAction(tr("&Open..."), this);
129 openAct->setShortcut(tr("Ctrl+O"));
130 connect(openAct, &QAction::triggered, this, &MainWindow::open);
131
132 const QList<QByteArray> imageFormats = QImageWriter::supportedImageFormats();
133 for (const QByteArray &format : imageFormats) {
134 QString text = tr("%1...").arg(QString(format).toUpper());
135
136 QAction *action = new QAction(text, this);
137 action->setData(format);
138 connect(action, &QAction::triggered, this, &MainWindow::save);
139 saveAsActs.append(action);
140 }
141
142 printAct = new QAction(tr("&Print..."), this);
143 connect(printAct, &QAction::triggered, scribbleArea, &ScribbleArea::print);
144
145 exitAct = new QAction(tr("E&xit"), this);
146 exitAct->setShortcut(tr("Ctrl+Q"));
147 connect(exitAct, &QAction::triggered, this, &QWidget::close);
148
149 clearScreenAct = new QAction(tr("&Clear Screen"), this);
150 clearScreenAct->setShortcut(tr("Ctrl+L"));
151 connect(clearScreenAct, &QAction::triggered,
152 scribbleArea, &ScribbleArea::clearImage);
153
154 aboutAct = new QAction(tr("&About"), this);
155 connect(aboutAct, &QAction::triggered, this, &MainWindow::about);
156
157 aboutQtAct = new QAction(tr("About &Qt"), this);
158 connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt);
159}
160//! [14]
161
162//! [15]
163void MainWindow::createMenus()
164//! [15] //! [16]
165{
166 saveAsMenu = new QMenu(tr("&Save As"), this);
167 saveAsMenu->addActions(saveAsActs);
168
169 fileMenu = new QMenu(tr("&File"), this);
170 fileMenu->addAction(openAct);
171 fileMenu->addMenu(saveAsMenu);
172 fileMenu->addAction(printAct);
173 fileMenu->addSeparator();
174 fileMenu->addAction(exitAct);
175
176 optionMenu = new QMenu(tr("&Options"), this);
177 optionMenu->addAction(clearScreenAct);
178
179 helpMenu = new QMenu(tr("&Help"), this);
180 helpMenu->addAction(aboutAct);
181 helpMenu->addAction(aboutQtAct);
182
183 menuBar()->addMenu(fileMenu);
184 menuBar()->addMenu(optionMenu);
185 menuBar()->addMenu(helpMenu);
186}
187//! [16]
188
189//! [17]
190bool MainWindow::maybeSave()
191//! [17] //! [18]
192{
193 if (scribbleArea->isModified()) {
194 QMessageBox::StandardButton ret;
195 ret = QMessageBox::warning(this, tr("Scribble"),
196 tr("The image has been modified.\n"
197 "Do you want to save your changes?"),
198 QMessageBox::Save | QMessageBox::Discard
199 | QMessageBox::Cancel);
200 if (ret == QMessageBox::Save) {
201 return saveFile("png");
202 } else if (ret == QMessageBox::Cancel) {
203 return false;
204 }
205 }
206 return true;
207}
208//! [18]
209
210//! [19]
211bool MainWindow::saveFile(const QByteArray &fileFormat)
212//! [19] //! [20]
213{
214 QString initialPath = QDir::currentPath() + "/untitled." + fileFormat;
215
216 QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"),
217 initialPath,
218 tr("%1 Files (*.%2);;All Files (*)")
219 .arg(QString::fromLatin1(fileFormat.toUpper()))
220 .arg(QString::fromLatin1(fileFormat)));
221 if (fileName.isEmpty()) {
222 return false;
223 } else {
224 return scribbleArea->saveImage(fileName, fileFormat.constData());
225 }
226}
227//! [20]
228