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 "screenshot.h"
54
55//! [0]
56Screenshot::Screenshot()
57 : screenshotLabel(new QLabel(this))
58{
59 screenshotLabel->setSizePolicy(hor: QSizePolicy::Expanding, ver: QSizePolicy::Expanding);
60 screenshotLabel->setAlignment(Qt::AlignCenter);
61
62 const QRect screenGeometry = screen()->geometry();
63 screenshotLabel->setMinimumSize(minw: screenGeometry.width() / 8, minh: screenGeometry.height() / 8);
64
65 QVBoxLayout *mainLayout = new QVBoxLayout(this);
66 mainLayout->addWidget(screenshotLabel);
67
68 QGroupBox *optionsGroupBox = new QGroupBox(tr(s: "Options"), this);
69 delaySpinBox = new QSpinBox(optionsGroupBox);
70 delaySpinBox->setSuffix(tr(s: " s"));
71 delaySpinBox->setMaximum(60);
72
73 connect(sender: delaySpinBox, signal: QOverload<int>::of(ptr: &QSpinBox::valueChanged),
74 receiver: this, slot: &Screenshot::updateCheckBox);
75
76 hideThisWindowCheckBox = new QCheckBox(tr(s: "Hide This Window"), optionsGroupBox);
77
78 QGridLayout *optionsGroupBoxLayout = new QGridLayout(optionsGroupBox);
79 optionsGroupBoxLayout->addWidget(new QLabel(tr(s: "Screenshot Delay:"), this), row: 0, column: 0);
80 optionsGroupBoxLayout->addWidget(delaySpinBox, row: 0, column: 1);
81 optionsGroupBoxLayout->addWidget(hideThisWindowCheckBox, row: 1, column: 0, rowSpan: 1, columnSpan: 2);
82
83 mainLayout->addWidget(optionsGroupBox);
84
85 QHBoxLayout *buttonsLayout = new QHBoxLayout;
86 newScreenshotButton = new QPushButton(tr(s: "New Screenshot"), this);
87 connect(sender: newScreenshotButton, signal: &QPushButton::clicked, receiver: this, slot: &Screenshot::newScreenshot);
88 buttonsLayout->addWidget(newScreenshotButton);
89 QPushButton *saveScreenshotButton = new QPushButton(tr(s: "Save Screenshot"), this);
90 connect(sender: saveScreenshotButton, signal: &QPushButton::clicked, receiver: this, slot: &Screenshot::saveScreenshot);
91 buttonsLayout->addWidget(saveScreenshotButton);
92 QPushButton *quitScreenshotButton = new QPushButton(tr(s: "Quit"), this);
93 quitScreenshotButton->setShortcut(Qt::CTRL + Qt::Key_Q);
94 connect(sender: quitScreenshotButton, signal: &QPushButton::clicked, receiver: this, slot: &QWidget::close);
95 buttonsLayout->addWidget(quitScreenshotButton);
96 buttonsLayout->addStretch();
97 mainLayout->addLayout(layout: buttonsLayout);
98
99 shootScreen();
100 delaySpinBox->setValue(5);
101
102 setWindowTitle(tr(s: "Screenshot"));
103 resize(w: 300, h: 200);
104}
105//! [0]
106
107//! [1]
108void Screenshot::resizeEvent(QResizeEvent * /* event */)
109{
110 QSize scaledSize = originalPixmap.size();
111 scaledSize.scale(s: screenshotLabel->size(), mode: Qt::KeepAspectRatio);
112 if (scaledSize != screenshotLabel->pixmap(Qt::ReturnByValue).size())
113 updateScreenshotLabel();
114}
115//! [1]
116
117//! [2]
118void Screenshot::newScreenshot()
119{
120 if (hideThisWindowCheckBox->isChecked())
121 hide();
122 newScreenshotButton->setDisabled(true);
123
124 QTimer::singleShot(interval: delaySpinBox->value() * 1000, receiver: this, slot: &Screenshot::shootScreen);
125}
126//! [2]
127
128//! [3]
129void Screenshot::saveScreenshot()
130{
131 const QString format = "png";
132 QString initialPath = QStandardPaths::writableLocation(type: QStandardPaths::PicturesLocation);
133 if (initialPath.isEmpty())
134 initialPath = QDir::currentPath();
135 initialPath += tr(s: "/untitled.") + format;
136
137 QFileDialog fileDialog(this, tr(s: "Save As"), initialPath);
138 fileDialog.setAcceptMode(QFileDialog::AcceptSave);
139 fileDialog.setFileMode(QFileDialog::AnyFile);
140 fileDialog.setDirectory(initialPath);
141 QStringList mimeTypes;
142 const QList<QByteArray> baMimeTypes = QImageWriter::supportedMimeTypes();
143 for (const QByteArray &bf : baMimeTypes)
144 mimeTypes.append(t: QLatin1String(bf));
145 fileDialog.setMimeTypeFilters(mimeTypes);
146 fileDialog.selectMimeTypeFilter(filter: "image/" + format);
147 fileDialog.setDefaultSuffix(format);
148 if (fileDialog.exec() != QDialog::Accepted)
149 return;
150 const QString fileName = fileDialog.selectedFiles().first();
151 if (!originalPixmap.save(fileName)) {
152 QMessageBox::warning(parent: this, title: tr(s: "Save Error"), text: tr(s: "The image could not be saved to \"%1\".")
153 .arg(a: QDir::toNativeSeparators(pathName: fileName)));
154 }
155}
156//! [3]
157
158//! [4]
159void Screenshot::shootScreen()
160{
161 QScreen *screen = QGuiApplication::primaryScreen();
162 if (const QWindow *window = windowHandle())
163 screen = window->screen();
164 if (!screen)
165 return;
166
167 if (delaySpinBox->value() != 0)
168 QApplication::beep();
169
170 originalPixmap = screen->grabWindow(window: 0);
171 updateScreenshotLabel();
172
173 newScreenshotButton->setDisabled(false);
174 if (hideThisWindowCheckBox->isChecked())
175 show();
176}
177//! [4]
178
179//! [6]
180void Screenshot::updateCheckBox()
181{
182 if (delaySpinBox->value() == 0) {
183 hideThisWindowCheckBox->setDisabled(true);
184 hideThisWindowCheckBox->setChecked(false);
185 } else {
186 hideThisWindowCheckBox->setDisabled(false);
187 }
188}
189//! [6]
190
191
192//! [10]
193void Screenshot::updateScreenshotLabel()
194{
195 screenshotLabel->setPixmap(originalPixmap.scaled(s: screenshotLabel->size(),
196 aspectMode: Qt::KeepAspectRatio,
197 mode: Qt::SmoothTransformation));
198}
199//! [10]
200

source code of qtbase/examples/widgets/desktop/screenshot/screenshot.cpp