on xenial help sign in
Add a plugin to take screenshots on vol up + vol down
7ce9d83Alberto Aguirre
debian/unity8-private.install+1
@@ -5,6 +5,7 @@ usr/lib/*/unity8/qml/LightDM
5usr/lib/*/unity8/qml/Lights
5usr/lib/*/unity8/qml/Lights
6usr/lib/*/unity8/qml/Powerd
6usr/lib/*/unity8/qml/Powerd
7usr/lib/*/unity8/qml/SessionBroadcast
7usr/lib/*/unity8/qml/SessionBroadcast
8+usr/lib/*/unity8/qml/Screenshotter
8usr/lib/*/unity8/qml/Ubuntu
9usr/lib/*/unity8/qml/Ubuntu
9usr/lib/*/unity8/qml/Unity
10usr/lib/*/unity8/qml/Unity
10usr/lib/*/unity8/qml/Utils
11usr/lib/*/unity8/qml/Utils
plugins/CMakeLists.txt+1
@@ -18,6 +18,7 @@ add_subdirectory(Lights)
18add_subdirectory(Dash)
18add_subdirectory(Dash)
19add_subdirectory(Powerd)
19add_subdirectory(Powerd)
20add_subdirectory(SessionBroadcast)
20add_subdirectory(SessionBroadcast)
21+add_subdirectory(Screenshotter)
21add_subdirectory(Ubuntu)
22add_subdirectory(Ubuntu)
22add_subdirectory(Unity)
23add_subdirectory(Unity)
23add_subdirectory(Utils)
24add_subdirectory(Utils)
plugins/Screenshotter/CMakeLists.txtnew file+13
@@ -0,0 +1,13 @@
1+include_directories(
2+ ${CMAKE_CURRENT_BINARY_DIR}
3+)
4+
5+set(SCREENSHOTTERSOURCES
6+ screenshotter.cpp
7+ plugin.cpp
8+)
9+
10+add_library(Screenshotter-qml MODULE ${SCREENSHOTTERSOURCES})
11+qt5_use_modules(Screenshotter-qml Qml Gui Quick)
12+
13+add_unity8_plugin(Screenshotter 0.1 Screenshotter TARGETS Screenshotter-qml)
plugins/Screenshotter/Screenshotter.qmltypesnew file+17
@@ -0,0 +1,17 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -nonrelocatable Screenshotter 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "ScreenShotter"
12+ prototype: "QObject"
13+ exports: ["Screenshotter/Screenshotter 0.1"]
14+ exportMetaObjectRevisions: [0]
15+ Method { name: "takeScreenshot" }
16+ }
17+}
plugins/Screenshotter/plugin.cppnew file+28
@@ -0,0 +1,28 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authors: Alberto Aguirre <alberto.aguirre@canonical.com>
17+ */
18+
19+#include "plugin.h"
20+#include "screenshotter.h"
21+
22+#include <QtQml/qqml.h>
23+
24+void ScreenshotterPlugin::registerTypes(const char *uri)
25+{
26+ Q_ASSERT(uri == QLatin1String("Screenshotter"));
27+ qmlRegisterType<ScreenShotter>(uri, 0, 1, "Screenshotter");
28+}
plugins/Screenshotter/plugin.hnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authors: Alberto Aguirre <alberto.aguirre@canonical.com>
17+ */
18+
19+#ifndef SCREENSHOTTER_PLUGIN_H
20+#define SCREENSHOTTER_PLUGIN_H
21+
22+#include <QtQml/QQmlExtensionPlugin>
23+
24+class ScreenshotterPlugin : public QQmlExtensionPlugin
25+{
26+ Q_OBJECT
27+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
28+
29+public:
30+ void registerTypes(const char *uri);
31+};
32+
33+#endif // SCREENSHOTTER_PLUGIN_H
plugins/Screenshotter/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module Screenshotter
2+plugin Screenshotter-qml
3+typeinfo Screenshotter.qmltypes
plugins/Screenshotter/screenshotter.cppnew file+105
@@ -0,0 +1,105 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authors: Alberto Aguirre <alberto.aguirre@canonical.com>
17+ */
18+
19+#include "screenshotter.h"
20+
21+#include <QUuid>
22+#include <QChar>
23+#include <QString>
24+#include <QStringList>
25+#include <QStandardPaths>
26+#include <QtGui/QGuiApplication>
27+#include <QtQuick/QQuickWindow>
28+
29+#include <QDebug>
30+
31+ScreenShotter::ScreenShotter(QObject *parent)
32+ : QObject(parent),
33+ screenshotsDir(QStandardPaths::displayName(QStandardPaths::PicturesLocation)),
34+ screenshotQuality(90)
35+{
36+ screenshotsDir.mkdir("Screenshots");
37+ screenshotsDir.cd("Screenshots");
38+}
39+
40+void ScreenShotter::takeScreenshot()
41+{
42+ QWindowList windows = QGuiApplication::topLevelWindows();
43+ if (windows.empty())
44+ {
45+ qWarning() << "ScreenShotter: no top level windows found!";
46+ return;
47+ }
48+
49+ QQuickWindow *main_window = qobject_cast<QQuickWindow *>(windows[0]);
50+ if (!main_window)
51+ {
52+ qWarning() << "ScreenShotter: can only take screenshots of QQuickWindows";
53+ return;
54+ }
55+
56+ QImage snapshot = main_window->grabWindow();
57+ if (!snapshot.save(generateName(), "JPG", screenshotQuality))
58+ qWarning() << "ScreenShotter: failed to save snapshot!";
59+}
60+
61+QString ScreenShotter::generateUniqueNum()
62+{
63+ // First lets look for existing files using our numbering pattern
64+ QStringList nameFilter;
65+ nameFilter << "screenshot????.jpg";
66+ QStringList fileList = screenshotsDir.entryList(nameFilter, QDir::Files, QDir::Name | QDir::Reversed);
67+
68+ if (!fileList.empty())
69+ {
70+ Q_FOREACH(QString const& fileName, fileList)
71+ {
72+ // Just the the four digit number
73+ QString fileNumber = fileName.mid(10, 4);
74+ bool ok = false;
75+ int num = fileNumber.toInt(&ok) + 1;
76+ if (!ok)
77+ continue;
78+
79+ // OK it's an actual number
80+ if (num <= 9999)
81+ {
82+ // Produce a string that has the next sequential number, appending 0's when necessary
83+ return QString("%1").arg(num, 4, 10, QChar('0'));
84+ }
85+ else
86+ {
87+ // 10000 screenshots huh? ummm, well let's start using uuids then...
88+ QString uuid = QUuid::createUuid().toString();
89+ // Remove the curly brackets
90+ return uuid.mid(1, 36);
91+ }
92+ }
93+ }
94+ //No files exist using our numbering scheme
95+ return QString("0000");
96+}
97+
98+QString ScreenShotter::generateName()
99+{
100+ QString fileName = screenshotsDir.absolutePath();
101+ fileName.append("/screenshot");
102+ fileName.append(generateUniqueNum());
103+ fileName.append(".jpg");
104+ return fileName;
105+}
plugins/Screenshotter/screenshotter.hnew file+42
@@ -0,0 +1,42 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authors: Alberto Aguirre <alberto.aguirre@canonical.com>
17+ */
18+
19+#ifndef SNAPSHOTTER_H
20+#define SNAPSHOTTER_H
21+
22+#include <QObject>
23+#include <QDir>
24+
25+class ScreenShotter: public QObject
26+{
27+ Q_OBJECT
28+
29+public:
30+ explicit ScreenShotter(QObject *parent = 0);
31+
32+public Q_SLOTS:
33+ void takeScreenshot();
34+
35+private:
36+ QString generateName();
37+ QString generateUniqueNum();
38+ QDir screenshotsDir;
39+ int screenshotQuality;
40+};
41+
42+#endif
qml/Shell.qml+67
@@ -30,6 +30,7 @@ import Utils 0.1
30import LightDM 0.1 as LightDM
30import LightDM 0.1 as LightDM
31import Powerd 0.1
31import Powerd 0.1
32import SessionBroadcast 0.1
32import SessionBroadcast 0.1
33+import Screenshotter 0.1
33import "Greeter"
34import "Greeter"
34import "Launcher"
35import "Launcher"
35import "Panel"
36import "Panel"
@@ -128,12 +129,18 @@ Item {
128 objectName: "dashCommunicator"
129 objectName: "dashCommunicator"
129 }
130 }
130
131
132+ Screenshotter {
133+ id: screenShotter
134+ objectName: "screenShotter"
135+ }
136+
131 WindowKeysFilter {
137 WindowKeysFilter {
132 // Handle but do not filter out volume keys
138 // Handle but do not filter out volume keys
133 Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; }
139 Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; }
134 Keys.onVolumeDownPressed: { volumeControl.volumeDown(); event.accepted = false; }
140 Keys.onVolumeDownPressed: { volumeControl.volumeDown(); event.accepted = false; }
135
141
136 Keys.onPressed: {
142 Keys.onPressed: {
143+ screenshotAnimation.onKeyPressed(event.key);
137 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
144 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
138 dialogs.onPowerKeyPressed();
145 dialogs.onPowerKeyPressed();
139 event.accepted = true;
146 event.accepted = true;
@@ -143,6 +150,7 @@ Item {
143 }
150 }
144
151
145 Keys.onReleased: {
152 Keys.onReleased: {
153+ screenshotAnimation.onKeyReleased(event.key);
146 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
154 if (event.key == Qt.Key_PowerOff || event.key == Qt.Key_PowerDown) {
147 dialogs.onPowerKeyReleased();
155 dialogs.onPowerKeyReleased();
148 event.accepted = true;
156 event.accepted = true;
@@ -687,6 +695,65 @@ Item {
687 }
695 }
688 }
696 }
689 }
697 }
698+ }
699+
700+ Rectangle {
701+ id: screenshotAnimation
702+ z: edgeDemo.z + 10
703+ enabled: false
704+ visible: false
705+ color: "white"
706+ anchors.fill: parent
707+ opacity: 0.0
708+
709+ QtObject {
710+ id: state
711+ property bool volumeUp: false
712+ property bool volumeDown: false
713+ }
714+
715+ function onKeyPressed(key) {
716+ if (key == Qt.Key_VolumeUp)
717+ state.volumeUp = true;
718+ else if (key == Qt.Key_VolumeDown)
719+ state.volumeDown = true;
720+ if (state.volumeDown && state.volumeUp) {
721+ enabled = true;
722+ visible = true;
723+ screenshotFadeIn.start();
724+ }
725+ }
726+
727+ function onKeyReleased(key) {
728+ if (key == Qt.Key_VolumeUp)
729+ state.volumeUp = false;
730+ else if (key == Qt.Key_VolumeDown)
731+ state.volumeDown = false;
732+ }
733+
734+ NumberAnimation on opacity {
735+ id: screenshotFadeIn
736+ from: 0.0
737+ to: 1.0
738+ onStopped: {
739+ if (screenshotAnimation.enabled && screenshotAnimation.visible) {
740+ screenshotFadeOut.start()
741+ }
742+ }
743+ }
744+
745+ NumberAnimation on opacity {
746+ id: screenshotFadeOut
747+ from: 1.0
748+ to: 0.0
749+ onStopped: {
750+ if (screenshotAnimation.enabled && screenshotAnimation.visible) {
751+ screenShotter.takeScreenshot();
752+ screenshotAnimation.enabled = false
753+ screenshotAnimation.visible = false
754+ }
755+ }
756+ }
690 }
757 }
691
758
692}
759}