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 <QTemporaryDir>
23 #include <QtGui/QImage>
24 #include <QtGui/QGuiApplication>
25 #include <QtQuick/QQuickWindow>
26 #include <QtConcurrent/QtConcurrentRun>
27 
28 #include <QDebug>
29 
30 bool saveScreenshot(const QImage &screenshot, const QString &filename, const QString &format, int quality)
31 {
32  if (!screenshot.save(filename, format.toLatin1().data(), quality)) {
33  qWarning() << "ScreenGrabber: failed to save snapshot!";
34  return false;
35  }
36 
37  return true;
38 }
39 
40 ScreenGrabber::ScreenGrabber(QObject *parent)
41  : QObject(parent)
42 {
43  QDir screenshotsDir;
44  if (qEnvironmentVariableIsSet("UNITY_TESTING")) {
45  qDebug() << "Using test environment";
46  QTemporaryDir tDir;
47  tDir.setAutoRemove(false);
48  screenshotsDir = tDir.path();
49  } else {
50  qDebug() << "Using real environment";
51  screenshotsDir = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
52  }
53  screenshotsDir.mkpath(QStringLiteral("Screenshots"));
54  screenshotsDir.cd(QStringLiteral("Screenshots"));
55  if (screenshotsDir.exists()) {
56  fileNamePrefix = screenshotsDir.absolutePath();
57  fileNamePrefix.append("/screenshot");
58  } else {
59  qWarning() << "ScreenGrabber: failed to create directory at: " << screenshotsDir.absolutePath();
60  }
61 }
62 
63 void ScreenGrabber::captureAndSave(int angle)
64 {
65  if (fileNamePrefix.isEmpty())
66  {
67  qWarning() << "ScreenShotter: no directory to save screenshot";
68  return;
69  }
70 
71  const QWindowList windows = QGuiApplication::topLevelWindows();
72  if (windows.empty())
73  {
74  qWarning() << "ScreenShotter: no top level windows found!";
75  return;
76  }
77 
78  QQuickWindow *main_window = qobject_cast<QQuickWindow *>(windows[0]);
79  if (!main_window)
80  {
81  qWarning() << "ScreenShotter: can only take screenshots of QQuickWindows";
82  return;
83  }
84 
85  const QImage screenshot = main_window->grabWindow().transformed(QTransform().rotate(angle));
86  const QString filename = makeFileName();
87  qDebug() << "Saving screenshot to" << filename;
88  auto saveOp = QtConcurrent::run(saveScreenshot, screenshot, filename, getFormat(), screenshotQuality);
89  if (saveOp.result()) {
90  Q_EMIT screenshotSaved(filename);
91  }
92 }
93 
94 QString ScreenGrabber::makeFileName() const
95 {
96  QString fileName(fileNamePrefix);
97  fileName.append(QDateTime::currentDateTime().toString(QStringLiteral("yyyyMMdd_hhmmsszzz")));
98  fileName.append(".");
99  fileName.append(getFormat());
100  return fileName;
101 }
102 
103 QString ScreenGrabber::getFormat() const
104 {
105  //TODO: This should be configurable (perhaps through gsettings?)
106  return QStringLiteral("png");
107 }