Unity 8
screengrabber.cpp
1 /*
2  * Copyright (C) 2014-2015 Canonical, Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 3.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include "screengrabber.h"
18 
19 #include <QDir>
20 #include <QDateTime>
21 #include <QStandardPaths>
22 #include <QtGui/QImage>
23 #include <QtGui/QGuiApplication>
24 #include <QtQuick/QQuickWindow>
25 #include <QtConcurrent/QtConcurrentRun>
26 
27 #include <QDebug>
28 
29 bool saveScreenshot(const QImage &screenshot, const QString &filename, const QString &format, int quality)
30 {
31  if (!screenshot.save(filename, format.toLatin1().data(), quality)) {
32  qWarning() << "ScreenGrabber: failed to save snapshot!";
33  return false;
34  }
35 
36  return true;
37 }
38 
39 ScreenGrabber::ScreenGrabber(QObject *parent)
40  : QObject(parent)
41 {
42  QDir screenshotsDir;
43  if (qEnvironmentVariableIsSet("UNITY_TESTING")) {
44  qDebug() << "Using test environment";
45  QStandardPaths::setTestModeEnabled(true);
46  screenshotsDir = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
47  } else {
48  qDebug() << "Using real environment";
49  screenshotsDir = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
50  }
51  screenshotsDir.mkpath("Screenshots");
52  screenshotsDir.cd("Screenshots");
53  if (screenshotsDir.exists()) {
54  fileNamePrefix = screenshotsDir.absolutePath();
55  fileNamePrefix.append("/screenshot");
56  } else {
57  qWarning() << "ScreenGrabber: failed to create directory at: " << screenshotsDir.absolutePath();
58  }
59 }
60 
61 void ScreenGrabber::captureAndSave()
62 {
63  if (fileNamePrefix.isEmpty())
64  {
65  qWarning() << "ScreenShotter: no directory to save screenshot";
66  return;
67  }
68 
69  const QWindowList windows = QGuiApplication::topLevelWindows();
70  if (windows.empty())
71  {
72  qWarning() << "ScreenShotter: no top level windows found!";
73  return;
74  }
75 
76  QQuickWindow *main_window = qobject_cast<QQuickWindow *>(windows[0]);
77  if (!main_window)
78  {
79  qWarning() << "ScreenShotter: can only take screenshots of QQuickWindows";
80  return;
81  }
82 
83  const QImage screenshot = main_window->grabWindow();
84  const QString filename = makeFileName();
85  qDebug() << "Saving screenshot to" << filename;
86  auto saveOp = QtConcurrent::run(saveScreenshot, screenshot, filename, getFormat(), screenshotQuality);
87  if (saveOp.result()) {
88  Q_EMIT screenshotSaved(filename);
89  }
90 }
91 
92 QString ScreenGrabber::makeFileName() const
93 {
94  QString fileName(fileNamePrefix);
95  fileName.append(QDateTime::currentDateTime().toString("yyyyMMdd_hhmmsszzz"));
96  fileName.append(".");
97  fileName.append(getFormat());
98  return fileName;
99 }
100 
101 QString ScreenGrabber::getFormat() const
102 {
103  //TODO: This should be configurable (perhaps through gsettings?)
104  return "png";
105 }