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 "mainwindow.h"
52#include "scribblearea.h"
53
54#include <QApplication>
55#include <QColorDialog>
56#include <QFileDialog>
57#include <QImageWriter>
58#include <QInputDialog>
59#include <QMenuBar>
60#include <QMessageBox>
61#include <QCloseEvent>
62
63//! [0]
64MainWindow::MainWindow(QWidget *parent)
65 : QMainWindow(parent), scribbleArea(new ScribbleArea(this))
66{
67 setCentralWidget(scribbleArea);
68
69 createActions();
70 createMenus();
71
72 setWindowTitle(tr(s: "Scribble"));
73 resize(w: 500, h: 500);
74}
75//! [0]
76
77//! [1]
78void MainWindow::closeEvent(QCloseEvent *event)
79//! [1] //! [2]
80{
81 if (maybeSave())
82 event->accept();
83 else
84 event->ignore();
85}
86//! [2]
87
88//! [3]
89void MainWindow::open()
90//! [3] //! [4]
91{
92 if (maybeSave()) {
93 QString fileName = QFileDialog::getOpenFileName(parent: this,
94 caption: tr(s: "Open File"), dir: QDir::currentPath());
95 if (!fileName.isEmpty())
96 scribbleArea->openImage(fileName);
97 }
98}
99//! [4]
100
101//! [5]
102void MainWindow::save()
103//! [5] //! [6]
104{
105 QAction *action = qobject_cast<QAction *>(object: sender());
106 QByteArray fileFormat = action->data().toByteArray();
107 saveFile(fileFormat);
108}
109//! [6]
110
111//! [7]
112void MainWindow::penColor()
113//! [7] //! [8]
114{
115 QColor newColor = QColorDialog::getColor(initial: scribbleArea->penColor());
116 if (newColor.isValid())
117 scribbleArea->setPenColor(newColor);
118}
119//! [8]
120
121//! [9]
122void MainWindow::penWidth()
123//! [9] //! [10]
124{
125 bool ok;
126 int newWidth = QInputDialog::getInt(parent: this, title: tr(s: "Scribble"),
127 label: tr(s: "Select pen width:"),
128 value: scribbleArea->penWidth(),
129 minValue: 1, maxValue: 50, step: 1, ok: &ok);
130 if (ok)
131 scribbleArea->setPenWidth(newWidth);
132}
133//! [10]
134
135//! [11]
136void MainWindow::about()
137//! [11] //! [12]
138{
139 QMessageBox::about(parent: this, title: tr(s: "About Scribble"),
140 text: tr(s: "<p>The <b>Scribble</b> example shows how to use QMainWindow as the "
141 "base widget for an application, and how to reimplement some of "
142 "QWidget's event handlers to receive the events generated for "
143 "the application's widgets:</p><p> We reimplement the mouse event "
144 "handlers to facilitate drawing, the paint event handler to "
145 "update the application and the resize event handler to optimize "
146 "the application's appearance. In addition we reimplement the "
147 "close event handler to intercept the close events before "
148 "terminating the application.</p><p> The example also demonstrates "
149 "how to use QPainter to draw an image in real time, as well as "
150 "to repaint widgets.</p>"));
151}
152//! [12]
153
154//! [13]
155void MainWindow::createActions()
156//! [13] //! [14]
157{
158 openAct = new QAction(tr(s: "&Open..."), this);
159 openAct->setShortcuts(QKeySequence::Open);
160 connect(sender: openAct, signal: &QAction::triggered, receiver: this, slot: &MainWindow::open);
161
162 const QList<QByteArray> imageFormats = QImageWriter::supportedImageFormats();
163 for (const QByteArray &format : imageFormats) {
164 QString text = tr(s: "%1...").arg(a: QString::fromLatin1(str: format).toUpper());
165
166 QAction *action = new QAction(text, this);
167 action->setData(format);
168 connect(sender: action, signal: &QAction::triggered, receiver: this, slot: &MainWindow::save);
169 saveAsActs.append(t: action);
170 }
171
172 printAct = new QAction(tr(s: "&Print..."), this);
173 connect(sender: printAct, signal: &QAction::triggered, receiver: scribbleArea, slot: &ScribbleArea::print);
174
175 exitAct = new QAction(tr(s: "E&xit"), this);
176 exitAct->setShortcuts(QKeySequence::Quit);
177 connect(sender: exitAct, signal: &QAction::triggered, receiver: this, slot: &MainWindow::close);
178
179 penColorAct = new QAction(tr(s: "&Pen Color..."), this);
180 connect(sender: penColorAct, signal: &QAction::triggered, receiver: this, slot: &MainWindow::penColor);
181
182 penWidthAct = new QAction(tr(s: "Pen &Width..."), this);
183 connect(sender: penWidthAct, signal: &QAction::triggered, receiver: this, slot: &MainWindow::penWidth);
184
185 clearScreenAct = new QAction(tr(s: "&Clear Screen"), this);
186 clearScreenAct->setShortcut(tr(s: "Ctrl+L"));
187 connect(sender: clearScreenAct, signal: &QAction::triggered,
188 receiver: scribbleArea, slot: &ScribbleArea::clearImage);
189
190 aboutAct = new QAction(tr(s: "&About"), this);
191 connect(sender: aboutAct, signal: &QAction::triggered, receiver: this, slot: &MainWindow::about);
192
193 aboutQtAct = new QAction(tr(s: "About &Qt"), this);
194 connect(sender: aboutQtAct, signal: &QAction::triggered, qApp, slot: &QApplication::aboutQt);
195}
196//! [14]
197
198//! [15]
199void MainWindow::createMenus()
200//! [15] //! [16]
201{
202 saveAsMenu = new QMenu(tr(s: "&Save As"), this);
203 for (QAction *action : qAsConst(t&: saveAsActs))
204 saveAsMenu->addAction(action);
205
206 fileMenu = new QMenu(tr(s: "&File"), this);
207 fileMenu->addAction(action: openAct);
208 fileMenu->addMenu(menu: saveAsMenu);
209 fileMenu->addAction(action: printAct);
210 fileMenu->addSeparator();
211 fileMenu->addAction(action: exitAct);
212
213 optionMenu = new QMenu(tr(s: "&Options"), this);
214 optionMenu->addAction(action: penColorAct);
215 optionMenu->addAction(action: penWidthAct);
216 optionMenu->addSeparator();
217 optionMenu->addAction(action: clearScreenAct);
218
219 helpMenu = new QMenu(tr(s: "&Help"), this);
220 helpMenu->addAction(action: aboutAct);
221 helpMenu->addAction(action: aboutQtAct);
222
223 menuBar()->addMenu(menu: fileMenu);
224 menuBar()->addMenu(menu: optionMenu);
225 menuBar()->addMenu(menu: helpMenu);
226}
227//! [16]
228
229//! [17]
230bool MainWindow::maybeSave()
231//! [17] //! [18]
232{
233 if (scribbleArea->isModified()) {
234 QMessageBox::StandardButton ret;
235 ret = QMessageBox::warning(parent: this, title: tr(s: "Scribble"),
236 text: tr(s: "The image has been modified.\n"
237 "Do you want to save your changes?"),
238 buttons: QMessageBox::Save | QMessageBox::Discard
239 | QMessageBox::Cancel);
240 if (ret == QMessageBox::Save)
241 return saveFile(fileFormat: "png");
242 else if (ret == QMessageBox::Cancel)
243 return false;
244 }
245 return true;
246}
247//! [18]
248
249//! [19]
250bool MainWindow::saveFile(const QByteArray &fileFormat)
251//! [19] //! [20]
252{
253 QString initialPath = QDir::currentPath() + "/untitled." + fileFormat;
254
255 QString fileName = QFileDialog::getSaveFileName(parent: this, caption: tr(s: "Save As"),
256 dir: initialPath,
257 filter: tr(s: "%1 Files (*.%2);;All Files (*)")
258 .arg(a: QString::fromLatin1(str: fileFormat.toUpper()))
259 .arg(a: QString::fromLatin1(str: fileFormat)));
260 if (fileName.isEmpty())
261 return false;
262 return scribbleArea->saveImage(fileName, fileFormat: fileFormat.constData());
263}
264//! [20]
265

source code of qtbase/examples/widgets/widgets/scribble/mainwindow.cpp