diff --git a/linphone-desktop/assets/languages/en.ts b/linphone-desktop/assets/languages/en.ts index 873bef5f4..e246e3f03 100644 --- a/linphone-desktop/assets/languages/en.ts +++ b/linphone-desktop/assets/languages/en.ts @@ -357,6 +357,13 @@ Server url not configured. Display tooltips to discover Linphone Desktop + + Incall + + saveScreenshotTitle + + + MainWindow diff --git a/linphone-desktop/assets/languages/fr.ts b/linphone-desktop/assets/languages/fr.ts index 1047a8058..4e26fbdf4 100644 --- a/linphone-desktop/assets/languages/fr.ts +++ b/linphone-desktop/assets/languages/fr.ts @@ -345,6 +345,13 @@ Url du serveur non configurée. Afficher les tooltips pour découvrir Linphone Desktop + + Incall + + saveScreenshotTitle + + + IncomingCall diff --git a/linphone-desktop/src/components/camera/Camera.cpp b/linphone-desktop/src/components/camera/Camera.cpp index fd52c5e1c..c1740eacc 100644 --- a/linphone-desktop/src/components/camera/Camera.cpp +++ b/linphone-desktop/src/components/camera/Camera.cpp @@ -1,8 +1,8 @@ -#include "Camera.hpp" - +#include #include #include +#include "../../utils.hpp" #include "../core/CoreManager.hpp" #include "Camera.hpp" @@ -52,15 +52,10 @@ QOpenGLFramebufferObject *CameraRenderer::createFramebufferObject (const QSize & context_info->width = size.width(); context_info->height = size.height(); - shared_ptr linphone_call = m_camera->m_call->getLinphoneCall(); - linphone::CallState state = linphone_call->getState(); - - if (state == linphone::CallStateConnected || state == linphone::CallStateStreamsRunning) { - if (m_camera->m_is_preview) - CoreManager::getInstance()->getCore()->setNativePreviewWindowId(context_info); - else - linphone_call->setNativeVideoWindowId(context_info); - } + if (m_camera->m_is_preview) + CoreManager::getInstance()->getCore()->setNativePreviewWindowId(context_info); + else + m_camera->m_call->getLinphoneCall()->setNativeVideoWindowId(context_info); return new QOpenGLFramebufferObject(size, format); } @@ -95,9 +90,30 @@ Camera::~Camera () { } QQuickFramebufferObject::Renderer *Camera::createRenderer () const { - return new CameraRenderer(this); + m_renderer = new CameraRenderer(this); + return m_renderer; } +// ----------------------------------------------------------------------------- + +void Camera::takeScreenshot () { + m_screenshot = m_renderer->framebufferObject()->toImage(); +} + +void Camera::saveScreenshot (const QString &path) { + QString formatted_path = path.startsWith("file://") ? path.mid(sizeof("file://") - 1) : path; + QFileInfo info(formatted_path); + QString extension = info.suffix(); + + m_screenshot.save( + formatted_path, + extension.size() > 0 ? ::Utils::qStringToLinphoneString(extension).c_str() : "jpg", + 100 + ); +} + +// ----------------------------------------------------------------------------- + void Camera::mousePressEvent (QMouseEvent *) { setFocus(true); } diff --git a/linphone-desktop/src/components/camera/Camera.hpp b/linphone-desktop/src/components/camera/Camera.hpp index 3f0385c52..c26a389c6 100644 --- a/linphone-desktop/src/components/camera/Camera.hpp +++ b/linphone-desktop/src/components/camera/Camera.hpp @@ -1,17 +1,20 @@ #ifndef CAMERA_H_ #define CAMERA_H_ -#include "../call/CallModel.hpp" - +#include #include #include +#include "../call/CallModel.hpp" + // ============================================================================= class Camera; struct ContextInfo; class CameraRenderer : public QQuickFramebufferObject::Renderer { + friend class Camera; + public: CameraRenderer (const Camera *camera); ~CameraRenderer () = default; @@ -40,6 +43,9 @@ public: QQuickFramebufferObject::Renderer *createRenderer () const override; + Q_INVOKABLE void takeScreenshot (); + Q_INVOKABLE void saveScreenshot (const QString &path); + signals: void callChanged (CallModel *call); void isPreviewChanged (bool is_preview); @@ -54,6 +60,9 @@ private: bool m_is_preview = false; CallModel *m_call = nullptr; ContextInfo *m_context_info; + + mutable CameraRenderer *m_renderer; + QImage m_screenshot; }; #endif // CAMERA_H_ diff --git a/linphone-desktop/ui/modules/Linphone/Chat/FileMessage.qml b/linphone-desktop/ui/modules/Linphone/Chat/FileMessage.qml index 3eae0bc43..c86569c9d 100644 --- a/linphone-desktop/ui/modules/Linphone/Chat/FileMessage.qml +++ b/linphone-desktop/ui/modules/Linphone/Chat/FileMessage.qml @@ -183,8 +183,8 @@ Row { id: fileDialog folder: shortcuts.home - title: qsTr('downloadFileTitle') selectExisting: false + title: qsTr('downloadFileTitle') onAccepted: proxyModel.downloadFile(index, fileUrl) } diff --git a/linphone-desktop/ui/views/App/Calls/Incall.qml b/linphone-desktop/ui/views/App/Calls/Incall.qml index c38651ae5..5f043a695 100644 --- a/linphone-desktop/ui/views/App/Calls/Incall.qml +++ b/linphone-desktop/ui/views/App/Calls/Incall.qml @@ -1,4 +1,5 @@ import QtQuick 2.7 +import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.3 import Common 1.0 @@ -84,13 +85,31 @@ Rectangle { id: cameraActions anchors.right: parent.right - active: Boolean(call.videoInputEnabled) + active: Boolean(call.videoInputEnabled) && call.status !== CallModel.CallStatusEnded sourceComponent: ActionBar { iconSize: CallStyle.header.iconSize ActionButton { icon: 'screenshot' + + FileDialog { + id: fileDialog + + folder: shortcuts.home + selectExisting: false + title: qsTr('saveScreenshotTitle') + + onAccepted: cameraLoader.item.saveScreenshot(fileUrl) + } + + onClicked: { + // TODO: At this moment, FileDialog does not support default filename, use this name in the future: + //'linphone ' + ((new Date()).toLocaleString(Qt.locale(), 'yyyy-MM-dd hh:mm:ss')) + '.jpg' + + cameraLoader.item.takeScreenshot() + fileDialog.open() + } } ActionButton { @@ -186,8 +205,9 @@ Rectangle { } Loader { - anchors.centerIn: parent + id: cameraLoader + anchors.centerIn: parent sourceComponent: call.videoInputEnabled ? camera : avatar } } @@ -200,6 +220,8 @@ Rectangle { Layout.fillWidth: true Layout.preferredHeight: CallStyle.actionArea.height + visible: call.status !== CallModel.CallStatusEnded + GridLayout { anchors { left: parent.left