1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-04-21 21:52:03 +02:00

feature: save participant's view

Change-Id: I790f10542aed306a7416a4ce79f2eaf7a770135a
Gitlab: #698
This commit is contained in:
Nicolas Vengeon 2023-01-10 16:47:18 -05:00 committed by Sébastien Blin
parent 9ffbf4ae1c
commit 86b84ea17e
22 changed files with 395 additions and 18 deletions

View file

@ -36,6 +36,7 @@ extern const QString defaultDownloadPath;
#define KEYS \
X(MinimizeOnClose, true) \
X(DownloadPath, defaultDownloadPath) \
X(ScreenshotPath, {}) \
X(EnableNotifications, true) \
X(EnableTypingIndicator, true) \
X(EnableReadReceipt, true) \

View file

@ -553,7 +553,7 @@ CallAdapter::fillParticipantData(QJsonObject& participant) const
auto uri = participant[URI].toString();
participant[ISLOCAL] = false;
if (uri == accInfo.profileInfo.uri && participant[DEVICE] == getCurrentDeviceId(accInfo)) {
participant[BESTNAME] = tr("me");
participant[BESTNAME] = tr("Me");
participant[ISLOCAL] = true;
} else {
try {
@ -1145,6 +1145,27 @@ CallAdapter::updateAdvancedInformation()
}
}
bool
CallAdapter::takeScreenshot(const QImage& image, const QString& path)
{
QString name = QString("%1 %2")
.arg(tr("Screenshot"))
.arg(QDateTime::currentDateTime().toString(Qt::ISODate));
bool fileAlreadyExists = true;
int nb = 0;
QString filePath = QString("%1%2.png").arg(path).arg(name);
while (fileAlreadyExists) {
filePath = QString("%1%2.png").arg(path).arg(name);
if (nb)
filePath = QString("%1(%2).png").arg(filePath).arg(QString::number(nb));
QFileInfo check_file(filePath);
fileAlreadyExists = check_file.exists() && check_file.isFile();
nb++;
}
return image.save(filePath, "PNG");
}
void
CallAdapter::preventScreenSaver(bool state)
{

View file

@ -98,6 +98,8 @@ public:
Q_INVOKABLE void setCallInfo();
Q_INVOKABLE void updateAdvancedInformation();
Q_INVOKABLE bool takeScreenshot(const QImage &image, const QString &path);
Q_SIGNALS:
void callStatusChanged(int index, const QString& accountId, const QString& convUid);
void callInfosChanged(const QVariant& infos, const QString& accountId, const QString& convUid);

View file

@ -49,6 +49,7 @@ MenuItem {
property int itemTextMargin: 20
signal clicked
property bool itemHovered: menuItemContentRect.hovered
contentItem: AbstractButton {
id: menuItemContentRect

View file

@ -298,6 +298,8 @@ Item {
property string lowerHand: qsTr("Lower hand")
property string raiseHand: qsTr("Raise hand")
property string layoutSettings: qsTr("Layout settings")
property string tileScreenshot: qsTr("Take tile screenshot")
property string screenshotTaken: qsTr("Screenshot saved to %1")
//advanced information
property string renderersInformation: qsTr("Renderers information")
@ -508,15 +510,16 @@ Item {
// Context Menu
property string saveFile: qsTr("Save file")
property string openLocation: qsTr("Open location")
property string me: qsTr("Me")
// Updates
property string betaInstall: qsTr("Install beta version")
property string checkForUpdates: qsTr("Check for updates now")
property string enableAutoUpdates: qsTr("Enable/Disable automatic updates")
property string tipAutoUpdate: qsTr("toggle automatic updates")
property string tipAutoUpdate: qsTr("Toggle automatic updates")
property string updatesTitle: qsTr("Updates")
property string updateDialogTitle: qsTr("Update")
property string updateFound: qsTr("A new version of Jami was found\n Would you like to update now?")
property string updateFound: qsTr("A new version of Jami was found\nWould you like to update now?")
property string updateNotFound: qsTr("No new version of Jami was found")
property string updateCheckError: qsTr("An error occured when checking for a new version")
property string updateNetworkError: qsTr("Network error")
@ -538,7 +541,8 @@ Item {
// Recording Settings
property string tipRecordFolder: qsTr("Select a record directory")
property string quality: qsTr("Quality")
property string saveIn: qsTr("Save in")
property string saveRecordingsTo: qsTr("Save recordings to")
property string saveScreenshotsTo: qsTr("Save screenshots to")
property string callRecording: qsTr("Call Recording")
property string alwaysRecordCalls: qsTr("Always record calls")

View file

@ -146,6 +146,11 @@ Item {
property color spinboxBackgroundColor: darkTheme ? editBackgroundColor : selectedColor
property color spinboxBorderColor: darkTheme ? tintedBlue : Qt.rgba(0, 0.34, 0.6, 0.36)
//Toast
property color toastColor: darkTheme ? "#f0f0f0" : "#000000"
property color toastRectColor: !darkTheme ? "#f0f0f0" : "#000000"
property real toastFontSize: calcSize(15)
// Call buttons
property color acceptButtonGreen: "#4caf50"
property color acceptButtonHoverGreen: "#5db761"

View file

@ -174,10 +174,12 @@ MainApplication::init()
Qt::DirectConnection);
auto downloadPath = settingsManager_->getValue(Settings::Key::DownloadPath);
auto screenshotPath = settingsManager_->getValue(Settings::Key::ScreenshotPath);
auto allowTransferFromTrusted = settingsManager_->getValue(Settings::Key::AutoAcceptFiles)
.toBool();
auto acceptTransferBelow = settingsManager_->getValue(Settings::Key::AcceptTransferBelow).toInt();
lrcInstance_->accountModel().downloadDirectory = downloadPath.toString() + "/";
lrcInstance_->accountModel().screenshotDirectory = screenshotPath.toString();
lrcInstance_->accountModel().autoTransferFromTrusted = allowTransferFromTrusted;
lrcInstance_->accountModel().autoTransferSizeThreshold = acceptTransferBelow;

View file

@ -39,6 +39,7 @@ Item {
signal chatButtonClicked
signal fullScreenClicked
signal closeClicked
function closeContextMenuAndRelatedWindows() {
ContactPickerCreation.closeContactPicker()
@ -46,14 +47,22 @@ Item {
SelectScreenWindowCreation.destroySelectScreenWindow()
ScreenRubberBandCreation.destroyScreenRubberBandWindow()
PluginHandlerPickerCreation.closePluginHandlerPicker()
root.closeClicked()
callInformationOverlay.close()
}
// x, y position does not need to be translated
// since they all fill the call page
function openCallViewContextMenuInPos(x, y) {
function openCallViewContextMenuInPos(x, y,
hoveredOverlayUri,
hoveredOverlaySinkId,
hoveredOverVideoMuted)
{
callViewContextMenu.x = x
callViewContextMenu.y = y
callViewContextMenu.hoveredOverlayUri = hoveredOverlayUri
callViewContextMenu.hoveredOverlaySinkId = hoveredOverlaySinkId
callViewContextMenu.hoveredOverVideoMuted = hoveredOverVideoMuted
callViewContextMenu.openMenu()
}
@ -171,10 +180,16 @@ Item {
onTransferCallButtonClicked: openContactPicker(ContactList.TRANSFER)
onPluginItemClicked: openPluginsMenu()
onScreenshotTaken: {
toastManager.instantiateToast();
}
onRecordCallClicked: CallAdapter.recordThisCallToggle()
onOpenSelectionWindow: {
SelectScreenWindowCreation.createSelectScreenWindowObject(appWindow)
SelectScreenWindowCreation.showSelectScreenWindow(callPreviewId, windowSelection)
}
onScreenshotButtonHoveredChanged: {
participantsLayer.screenshotButtonHovered = screenshotButtonHovered
}
}
}

View file

@ -37,6 +37,12 @@ ContextMenuAutoLoader {
signal transferCallButtonClicked
signal recordCallClicked
signal openSelectionWindow
signal screenshotTaken
property bool screenshotButtonHovered: screenShot.itemHovered
property string hoveredOverlayUri: ""
property string hoveredOverlaySinkId: ""
property bool hoveredOverVideoMuted: true
property list<GeneralMenuItem> menuItems: [
GeneralMenuItem {
@ -194,8 +200,34 @@ ContextMenuAutoLoader {
CallAdapter.startTimerInformation();
callInformationOverlay.open()
}
},
GeneralMenuItem {
id: screenShot
canTrigger: hoveredOverlayUri !== "" && hoveredOverVideoMuted === false
itemName: JamiStrings.tileScreenshot
iconSource: JamiResources.baseline_camera_alt_24dp_svg
MaterialToolTip {
id: tooltip
parent: screenShot
visible: screenShot.itemHovered
delay: Qt.styleHints.mousePressAndHoldInterval
property bool isMe: CurrentAccount.uri === hoveredOverlayUri
text: isMe ? JamiStrings.me
: UtilsAdapter.getBestNameForUri(CurrentAccount.id, hoveredOverlayUri)
}
onClicked: {
if (CallAdapter.takeScreenshot(videoProvider.captureRawVideoFrame(hoveredOverlaySinkId),
UtilsAdapter.getDirScreenshot())) {
screenshotTaken()
}
}
}
]
Component.onCompleted: menuItemsToLoad = menuItems
}

View file

@ -62,7 +62,9 @@ RowLayout {
anchors.centerIn: parent
text: shortcut
text: shortcut2 === "" ?
shortcut :
shortcut + " + " + shortcut2
font.pointSize: JamiTheme.textFontSize + 3
font.weight: Font.DemiBold
color: JamiTheme.textColor

View file

@ -40,42 +40,52 @@ Window {
ListElement {
shortcut: "Ctrl + J"
shortcut2: ""
description: qsTr("Open account list")
}
ListElement {
shortcut: "Ctrl + L"
shortcut2: ""
description: qsTr("Focus conversations list")
}
ListElement {
shortcut: "Ctrl + R"
shortcut2: ""
description: qsTr("Requests list")
}
ListElement {
shortcut: "Ctrl + ↑"
shortcut2: ""
description: qsTr("Previous conversation")
}
ListElement {
shortcut: "Ctrl + ↓"
shortcut2: ""
description: qsTr("Next conversation")
}
ListElement {
shortcut: "Ctrl + F"
shortcut2: ""
description: qsTr("Search bar")
}
ListElement {
shortcut: "F11"
shortcut2: ""
description: qsTr("Full screen")
}
ListElement {
shortcut: "Ctrl + +"
shortcut2: ""
description: qsTr("Increase font size")
}
ListElement {
shortcut: "Ctrl + -"
shortcut2: ""
description: qsTr("Decrease font size")
}
ListElement {
shortcut: "Ctrl + 0"
shortcut2: ""
description: qsTr("Reset font size")
}
}
@ -85,34 +95,42 @@ Window {
ListElement {
shortcut: "Ctrl + Shift + C"
shortcut2: ""
description: qsTr("Start an audio call")
}
ListElement {
shortcut: "Ctrl + Shift + X"
shortcut2: ""
description: qsTr("Start a video call")
}
ListElement {
shortcut: "Ctrl + Shift + L"
shortcut2: ""
description: qsTr("Clear history")
}
ListElement {
shortcut: "Ctrl + Shift + B"
shortcut2: ""
description: qsTr("Block contact")
}
ListElement {
shortcut: "Ctrl + Shift + Delete"
shortcut2: ""
description: qsTr("Remove conversation")
}
ListElement {
shortcut: "Shift + Ctrl + A"
shortcut2: ""
description: qsTr("Accept contact request")
}
ListElement {
shortcut: "↑"
shortcut2: ""
description: qsTr("Edit last message")
}
ListElement {
shortcut: "Esc"
shortcut2: ""
description: qsTr("Cancel message edition")
}
}
@ -122,26 +140,32 @@ Window {
ListElement {
shortcut: "Ctrl + M"
shortcut2: ""
description: qsTr("Media settings")
}
ListElement {
shortcut: "Ctrl + G"
shortcut2: ""
description: qsTr("General settings")
}
ListElement {
shortcut: "Ctrl + I"
shortcut2: ""
description: qsTr("Account settings")
}
ListElement {
shortcut: "Ctrl + P"
shortcut2: ""
description: qsTr("Plugin settings")
}
ListElement {
shortcut: "Ctrl + Shift + N"
shortcut2: ""
description: qsTr("Open account creation wizard")
}
ListElement {
shortcut: "F10"
shortcut2: ""
description: qsTr("Open keyboard shortcut table")
}
}
@ -151,24 +175,34 @@ Window {
ListElement {
shortcut: "Ctrl + Y"
shortcut2: ""
description: qsTr("Answer an incoming call")
}
ListElement {
shortcut: "Ctrl + D"
shortcut2: ""
description: qsTr("End call")
}
ListElement {
shortcut: "Ctrl + Shift + D"
shortcut2: ""
description: qsTr("Decline the call request")
}
ListElement {
shortcut: "M"
shortcut2: ""
description: qsTr("Mute microphone")
}
ListElement {
shortcut: "V"
shortcut2: ""
description: qsTr("Stop camera")
}
ListElement {
shortcut: "Ctrl"
shortcut2: qsTr("Mouse middle click")
description: qsTr("Take tile screenshot")
}
}
Rectangle {

View file

@ -166,7 +166,10 @@ Rectangle {
onTapped: function (eventPoint, button) {
if (button === Qt.RightButton) {
callOverlay.openCallViewContextMenuInPos(eventPoint.position.x,
eventPoint.position.y)
eventPoint.position.y,
participantsLayer.hoveredOverlayUri,
participantsLayer.hoveredOverlaySinkId,
participantsLayer.hoveredOverVideoMuted)
}
}
}
@ -184,6 +187,7 @@ Rectangle {
ParticipantsLayer {
id: participantsLayer
anchors.fill: parent
anchors.centerIn: parent
anchors.margins: 1
@ -191,9 +195,18 @@ Rectangle {
participantsSide: callOverlay.participantsSide
}
ToastManager {
id: toastManager
anchors.fill: parent
function instantiateToast() {
instantiate(JamiStrings.screenshotTaken.arg(UtilsAdapter.getDirScreenshot()),1000,400)
}
}
LocalVideo {
id: previewRenderer
visible: (CurrentCall.isSharing || !CurrentCall.isVideoMuted)
&& !CurrentCall.isConference
@ -329,6 +342,11 @@ Rectangle {
openInCallConversation()
}
}
onCloseClicked: {
participantsLayer.hoveredOverlayUri = ""
participantsLayer.hoveredOverlaySinkId = ""
participantsLayer.hoveredOverVideoMuted = true
}
onChatButtonClicked: {
inCallMessageWebViewStack.visible ?

View file

@ -67,6 +67,18 @@ Item {
property string muteAlertMessage: ""
property bool muteAlertActive: false
property bool participantHovered: hoverIndicator.hovered
property bool isScreenshotButtonHovered: false
function takeScreenshot() {
if (!hoveredOverVideoMuted) {
if (CallAdapter.takeScreenshot(videoProvider.captureRawVideoFrame(hoveredOverlaySinkId),
UtilsAdapter.getDirScreenshot())) {
toastManager.instantiateToast();
}
}
}
onMuteAlertActiveChanged: {
if (muteAlertActive) {
alertTimer.restart()
@ -94,9 +106,11 @@ Item {
Rectangle {
z: -1
color: JamiTheme.buttonTintedBlue
border.color: JamiTheme.buttonTintedBlue
border.width: 2
color: "transparent"
radius: 10
visible:voiceActive
visible: voiceActive || isScreenshotButtonHovered
width: participantIsActive ? mediaDistRender.contentRect.width + 2 : undefined
height: participantIsActive ? mediaDistRender.contentRect.height + 2 : undefined
anchors.centerIn: participantIsActive ? parent : undefined
@ -109,7 +123,6 @@ Item {
anchors.margins: 2
rendererId: root.sinkId
crop: !participantIsActive
underlayItems: Avatar {
property real componentSize: Math.min(mediaDistRender.contentRect.width / 2, mediaDistRender.contentRect.height / 2)
height: componentSize
@ -140,7 +153,25 @@ Item {
anchors.centerIn: participantIsActive ? parent : undefined
anchors.fill: participantIsActive ? undefined : parent
TapHandler {
acceptedButtons: Qt.MiddleButton
acceptedModifiers: Qt.ControlModifier
onTapped: {
takeScreenshot()
}
}
MultiPointTouchArea {
anchors.fill: parent
minimumTouchPoints: 3
onPressed: {
takeScreenshot()
}
}
HoverHandler {
id: hoverIndicator
onPointChanged: {
participantRect.opacity = 1
fadeOutTimer.restart()
@ -164,6 +195,7 @@ Item {
// Participant buttons for moderation
ParticipantOverlayMenu {
id: overlayMenu
visible: isMe || meModerator
anchors.fill: parent
@ -209,6 +241,7 @@ Item {
RowLayout {
id: participantFootInfo
height: parent.height
anchors.verticalCenter: parent.verticalCenter
Text {

View file

@ -37,6 +37,10 @@ Item {
property bool inLine: CallParticipantsModel.conferenceLayout === CallParticipantsModel.ONE_WITH_SMALL
property bool participantsSide
property bool enableHideSpectators: CallParticipantsModel.count > 1 && CurrentCall.hideSpectators
property string hoveredOverlayUri: ""
property string hoveredOverlaySinkId: ""
property bool hoveredOverVideoMuted: true
property bool screenshotButtonHovered: false
onVisibleChanged: {
CurrentCall.hideSelf = UtilsAdapter.getAppValue(Settings.HideSelf)
@ -51,7 +55,10 @@ Item {
anchors.fill: parent
anchors.leftMargin: leftMargin_
isScreenshotButtonHovered: screenshotButtonHovered && hoveredOverlaySinkId === sinkId_
opacity: screenshotButtonHovered
? hoveredOverlaySinkId !== sinkId ? 0.1 : 1
: 1
sinkId: sinkId_
uri: uri_
deviceId: deviceId_
@ -70,6 +77,14 @@ Item {
participantIsModeratorMuted: audioModeratorMuted_
participantHandIsRaised: isHandRaised_
onParticipantHoveredChanged: {
if (participantHovered) {
hoveredOverlayUri = overlay.uri
hoveredOverlaySinkId = overlay.sinkId
hoveredOverVideoMuted = videoMuted_
}
}
Connections {
id: registeredNameFoundConnection

View file

@ -0,0 +1,72 @@
/*
* Copyright (C) 2023 Savoir-faire Linux Inc.
* Author: Vengeon Nicolas <nicolas.vengeon@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import net.jami.Constants 1.1
Rectangle {
id: root
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
width: textMessage.width + 20
height: textMessage.height + 10
anchors.topMargin: 10
radius: 15
color: JamiTheme.toastRectColor
property int duration
property int fadingTime
property string message
Component.onCompleted: {
anim.start();
}
Text {
id: textMessage
anchors.centerIn: root
text: message
font.pointSize: JamiTheme.toastFontSize
color: JamiTheme.toastColor
}
SequentialAnimation on opacity {
id: anim
running: false
NumberAnimation {
to: 0.9
duration: root.fadingTime
}
PauseAnimation {
duration: root.duration
}
NumberAnimation {
to: 0
duration: root.fadingTime
}
onRunningChanged: {
if (!running)
root.destroy();
}
}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (C) 2023 Savoir-faire Linux Inc.
* Author: Vengeon Nicolas <nicolas.vengeon@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
Item {
id: root
function instantiate(message, duration, fadingTime) {
var component = Qt.createComponent("Toast.qml");
var sprite = component.createObject(root, {message: message, duration: duration, fadingTime: fadingTime});
}
}

View file

@ -28,24 +28,32 @@ import net.jami.Constants 1.1
import "../../commoncomponents"
ColumnLayout {
id:root
id: root
property int itemWidth
property string recordPath: AVModel.getRecordPath()
property string screenshotPath: UtilsAdapter.getDirScreenshot()
onRecordPathChanged: {
if(recordPath === "") return
if(recordPath === "")
return
if(AVModel){
if(AVModel) {
AVModel.setRecordPath(recordPath)
}
}
onScreenshotPathChanged: {
if (screenshotPath === "")
return
UtilsAdapter.setScreenshotPath(screenshotPath)
}
FolderDialog {
id: recordPathDialog
title: JamiStrings.selectFolder
currentFolder: StandardPaths.writableLocation(StandardPaths.HomeLocation)
currentFolder: UtilsAdapter.getDirScreenshot()
options: FolderDialog.ShowDirsOnly
onAccepted: {
@ -54,6 +62,19 @@ ColumnLayout {
}
}
FolderDialog {
id: screenshotPathDialog
title: JamiStrings.selectFolder
currentFolder: StandardPaths.writableLocation(StandardPaths.PicturesLocation)
options: FolderDialog.ShowDirsOnly
onAccepted: {
var dir = UtilsAdapter.getAbsPath(folder.toString())
screenshotPath = dir
}
}
Timer{
id: updateRecordQualityTimer
@ -172,7 +193,7 @@ ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
text: JamiStrings.saveIn
text: JamiStrings.saveRecordingsTo
color: JamiTheme.textColor
font.pointSize: JamiTheme.settingsFontSize
font.kerning: true
@ -199,4 +220,41 @@ ColumnLayout {
onClicked: recordPathDialog.open()
}
}
RowLayout {
Layout.fillWidth: true
Layout.preferredHeight: JamiTheme.preferredFieldHeight
Layout.leftMargin: JamiTheme.preferredMarginSize
Label {
Layout.fillWidth: true
Layout.fillHeight: true
text: JamiStrings.saveScreenshotsTo
color: JamiTheme.textColor
font.pointSize: JamiTheme.settingsFontSize
font.kerning: true
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
MaterialButton {
id: screenshotPathButton
Layout.alignment: Qt.AlignRight
preferredWidth: itemWidth
preferredHeight: JamiTheme.preferredFieldHeight
toolTipText: UtilsAdapter.getDirScreenshot()
text: screenshotPath
iconSource: JamiResources.round_folder_24dp_svg
color: JamiTheme.buttonTintedGrey
hoveredColor: JamiTheme.buttonTintedGreyHovered
pressedColor: JamiTheme.buttonTintedGreyPressed
onClicked: screenshotPathDialog.open()
}
}
}

View file

@ -387,6 +387,22 @@ UtilsAdapter::getDirDocument()
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
}
QString
UtilsAdapter::getDirScreenshot()
{
QString screenshotPath = lrcInstance_->accountModel().screenshotDirectory;
if (screenshotPath.isEmpty()) {
QString folderName = "Jami";
auto picture = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
QDir dir;
dir.mkdir(picture + QDir::separator() + folderName);
screenshotPath = picture + QDir::separator() + folderName;
setScreenshotPath(screenshotPath);
lrcInstance_->accountModel().screenshotDirectory = screenshotPath;
}
return screenshotPath;
}
QString
UtilsAdapter::getDirDownload()
{
@ -425,6 +441,13 @@ UtilsAdapter::setDownloadPath(QString dir)
lrcInstance_->accountModel().downloadDirectory = dir + "/";
}
void
UtilsAdapter::setScreenshotPath(QString dir)
{
setAppValue(Settings::Key::ScreenshotPath, dir);
lrcInstance_->accountModel().screenshotDirectory = dir + QDir::separator();
}
void
UtilsAdapter::monitor(const bool& continuous)
{

View file

@ -107,9 +107,11 @@ public:
Q_INVOKABLE QVariant getAppValue(const Settings::Key key);
Q_INVOKABLE void setAppValue(const Settings::Key key, const QVariant& value);
Q_INVOKABLE QString getDirDocument();
Q_INVOKABLE QString getDirScreenshot();
Q_INVOKABLE QString getDirDownload();
Q_INVOKABLE void setRunOnStartUp(bool state);
Q_INVOKABLE void setDownloadPath(QString dir);
Q_INVOKABLE void setScreenshotPath(QString dir);
Q_INVOKABLE void monitor(const bool& continuous);
Q_INVOKABLE void clearInteractionsCache(const QString& accountId, const QString& convUid);
Q_INVOKABLE QVariantMap supportedLang();

View file

@ -117,6 +117,13 @@ VideoProvider::frame(const QString& id)
QString
VideoProvider::captureVideoFrame(const QString& id)
{
auto img = captureRawVideoFrame(id);
return Utils::byteArrayToBase64String(Utils::QImageToByteArray(img));
}
QImage
VideoProvider::captureRawVideoFrame(const QString& id)
{
QMutexLocker framesLk(&framesObjsMutex_);
if (auto* videoFrame = frame(id)) {
@ -127,7 +134,7 @@ VideoProvider::captureVideoFrame(const QString& id)
videoFrame->height(),
videoFrame->bytesPerLine(0),
imageFormat);
return Utils::byteArrayToBase64String(Utils::QImageToByteArray(img));
return img;
}
return {};
}

View file

@ -46,6 +46,7 @@ public:
Q_INVOKABLE void registerSink(const QString& id, QVideoSink* obj);
Q_INVOKABLE void unregisterSink(QVideoSink* obj);
Q_INVOKABLE QString captureVideoFrame(const QString& id);
Q_INVOKABLE QImage captureRawVideoFrame(const QString& id);
private Q_SLOTS:
void onRendererStarted(const QString& id, const QSize& size);

View file

@ -73,6 +73,7 @@ public:
* Should contains the full directory with the end marker (/ on linux for example)
*/
QString downloadDirectory;
QString screenshotDirectory;
/**
* Accept transfer from trusted contacts
*/