mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-04-22 06:02:03 +02:00
feature: save participant's view
Change-Id: I790f10542aed306a7416a4ce79f2eaf7a770135a Gitlab: #698
This commit is contained in:
parent
9ffbf4ae1c
commit
86b84ea17e
22 changed files with 395 additions and 18 deletions
|
@ -36,6 +36,7 @@ extern const QString defaultDownloadPath;
|
||||||
#define KEYS \
|
#define KEYS \
|
||||||
X(MinimizeOnClose, true) \
|
X(MinimizeOnClose, true) \
|
||||||
X(DownloadPath, defaultDownloadPath) \
|
X(DownloadPath, defaultDownloadPath) \
|
||||||
|
X(ScreenshotPath, {}) \
|
||||||
X(EnableNotifications, true) \
|
X(EnableNotifications, true) \
|
||||||
X(EnableTypingIndicator, true) \
|
X(EnableTypingIndicator, true) \
|
||||||
X(EnableReadReceipt, true) \
|
X(EnableReadReceipt, true) \
|
||||||
|
|
|
@ -553,7 +553,7 @@ CallAdapter::fillParticipantData(QJsonObject& participant) const
|
||||||
auto uri = participant[URI].toString();
|
auto uri = participant[URI].toString();
|
||||||
participant[ISLOCAL] = false;
|
participant[ISLOCAL] = false;
|
||||||
if (uri == accInfo.profileInfo.uri && participant[DEVICE] == getCurrentDeviceId(accInfo)) {
|
if (uri == accInfo.profileInfo.uri && participant[DEVICE] == getCurrentDeviceId(accInfo)) {
|
||||||
participant[BESTNAME] = tr("me");
|
participant[BESTNAME] = tr("Me");
|
||||||
participant[ISLOCAL] = true;
|
participant[ISLOCAL] = true;
|
||||||
} else {
|
} else {
|
||||||
try {
|
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
|
void
|
||||||
CallAdapter::preventScreenSaver(bool state)
|
CallAdapter::preventScreenSaver(bool state)
|
||||||
{
|
{
|
||||||
|
|
|
@ -98,6 +98,8 @@ public:
|
||||||
Q_INVOKABLE void setCallInfo();
|
Q_INVOKABLE void setCallInfo();
|
||||||
Q_INVOKABLE void updateAdvancedInformation();
|
Q_INVOKABLE void updateAdvancedInformation();
|
||||||
|
|
||||||
|
Q_INVOKABLE bool takeScreenshot(const QImage &image, const QString &path);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void callStatusChanged(int index, const QString& accountId, const QString& convUid);
|
void callStatusChanged(int index, const QString& accountId, const QString& convUid);
|
||||||
void callInfosChanged(const QVariant& infos, const QString& accountId, const QString& convUid);
|
void callInfosChanged(const QVariant& infos, const QString& accountId, const QString& convUid);
|
||||||
|
|
|
@ -49,6 +49,7 @@ MenuItem {
|
||||||
property int itemTextMargin: 20
|
property int itemTextMargin: 20
|
||||||
|
|
||||||
signal clicked
|
signal clicked
|
||||||
|
property bool itemHovered: menuItemContentRect.hovered
|
||||||
|
|
||||||
contentItem: AbstractButton {
|
contentItem: AbstractButton {
|
||||||
id: menuItemContentRect
|
id: menuItemContentRect
|
||||||
|
|
|
@ -298,6 +298,8 @@ Item {
|
||||||
property string lowerHand: qsTr("Lower hand")
|
property string lowerHand: qsTr("Lower hand")
|
||||||
property string raiseHand: qsTr("Raise hand")
|
property string raiseHand: qsTr("Raise hand")
|
||||||
property string layoutSettings: qsTr("Layout settings")
|
property string layoutSettings: qsTr("Layout settings")
|
||||||
|
property string tileScreenshot: qsTr("Take tile screenshot")
|
||||||
|
property string screenshotTaken: qsTr("Screenshot saved to %1")
|
||||||
|
|
||||||
//advanced information
|
//advanced information
|
||||||
property string renderersInformation: qsTr("Renderers information")
|
property string renderersInformation: qsTr("Renderers information")
|
||||||
|
@ -508,15 +510,16 @@ Item {
|
||||||
// Context Menu
|
// Context Menu
|
||||||
property string saveFile: qsTr("Save file")
|
property string saveFile: qsTr("Save file")
|
||||||
property string openLocation: qsTr("Open location")
|
property string openLocation: qsTr("Open location")
|
||||||
|
property string me: qsTr("Me")
|
||||||
|
|
||||||
// Updates
|
// Updates
|
||||||
property string betaInstall: qsTr("Install beta version")
|
property string betaInstall: qsTr("Install beta version")
|
||||||
property string checkForUpdates: qsTr("Check for updates now")
|
property string checkForUpdates: qsTr("Check for updates now")
|
||||||
property string enableAutoUpdates: qsTr("Enable/Disable automatic updates")
|
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 updatesTitle: qsTr("Updates")
|
||||||
property string updateDialogTitle: qsTr("Update")
|
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 updateNotFound: qsTr("No new version of Jami was found")
|
||||||
property string updateCheckError: qsTr("An error occured when checking for a new version")
|
property string updateCheckError: qsTr("An error occured when checking for a new version")
|
||||||
property string updateNetworkError: qsTr("Network error")
|
property string updateNetworkError: qsTr("Network error")
|
||||||
|
@ -538,7 +541,8 @@ Item {
|
||||||
// Recording Settings
|
// Recording Settings
|
||||||
property string tipRecordFolder: qsTr("Select a record directory")
|
property string tipRecordFolder: qsTr("Select a record directory")
|
||||||
property string quality: qsTr("Quality")
|
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 callRecording: qsTr("Call Recording")
|
||||||
property string alwaysRecordCalls: qsTr("Always record calls")
|
property string alwaysRecordCalls: qsTr("Always record calls")
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,11 @@ Item {
|
||||||
property color spinboxBackgroundColor: darkTheme ? editBackgroundColor : selectedColor
|
property color spinboxBackgroundColor: darkTheme ? editBackgroundColor : selectedColor
|
||||||
property color spinboxBorderColor: darkTheme ? tintedBlue : Qt.rgba(0, 0.34, 0.6, 0.36)
|
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
|
// Call buttons
|
||||||
property color acceptButtonGreen: "#4caf50"
|
property color acceptButtonGreen: "#4caf50"
|
||||||
property color acceptButtonHoverGreen: "#5db761"
|
property color acceptButtonHoverGreen: "#5db761"
|
||||||
|
|
|
@ -174,10 +174,12 @@ MainApplication::init()
|
||||||
Qt::DirectConnection);
|
Qt::DirectConnection);
|
||||||
|
|
||||||
auto downloadPath = settingsManager_->getValue(Settings::Key::DownloadPath);
|
auto downloadPath = settingsManager_->getValue(Settings::Key::DownloadPath);
|
||||||
|
auto screenshotPath = settingsManager_->getValue(Settings::Key::ScreenshotPath);
|
||||||
auto allowTransferFromTrusted = settingsManager_->getValue(Settings::Key::AutoAcceptFiles)
|
auto allowTransferFromTrusted = settingsManager_->getValue(Settings::Key::AutoAcceptFiles)
|
||||||
.toBool();
|
.toBool();
|
||||||
auto acceptTransferBelow = settingsManager_->getValue(Settings::Key::AcceptTransferBelow).toInt();
|
auto acceptTransferBelow = settingsManager_->getValue(Settings::Key::AcceptTransferBelow).toInt();
|
||||||
lrcInstance_->accountModel().downloadDirectory = downloadPath.toString() + "/";
|
lrcInstance_->accountModel().downloadDirectory = downloadPath.toString() + "/";
|
||||||
|
lrcInstance_->accountModel().screenshotDirectory = screenshotPath.toString();
|
||||||
lrcInstance_->accountModel().autoTransferFromTrusted = allowTransferFromTrusted;
|
lrcInstance_->accountModel().autoTransferFromTrusted = allowTransferFromTrusted;
|
||||||
lrcInstance_->accountModel().autoTransferSizeThreshold = acceptTransferBelow;
|
lrcInstance_->accountModel().autoTransferSizeThreshold = acceptTransferBelow;
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ Item {
|
||||||
|
|
||||||
signal chatButtonClicked
|
signal chatButtonClicked
|
||||||
signal fullScreenClicked
|
signal fullScreenClicked
|
||||||
|
signal closeClicked
|
||||||
|
|
||||||
function closeContextMenuAndRelatedWindows() {
|
function closeContextMenuAndRelatedWindows() {
|
||||||
ContactPickerCreation.closeContactPicker()
|
ContactPickerCreation.closeContactPicker()
|
||||||
|
@ -46,14 +47,22 @@ Item {
|
||||||
SelectScreenWindowCreation.destroySelectScreenWindow()
|
SelectScreenWindowCreation.destroySelectScreenWindow()
|
||||||
ScreenRubberBandCreation.destroyScreenRubberBandWindow()
|
ScreenRubberBandCreation.destroyScreenRubberBandWindow()
|
||||||
PluginHandlerPickerCreation.closePluginHandlerPicker()
|
PluginHandlerPickerCreation.closePluginHandlerPicker()
|
||||||
|
root.closeClicked()
|
||||||
callInformationOverlay.close()
|
callInformationOverlay.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// x, y position does not need to be translated
|
// x, y position does not need to be translated
|
||||||
// since they all fill the call page
|
// since they all fill the call page
|
||||||
function openCallViewContextMenuInPos(x, y) {
|
function openCallViewContextMenuInPos(x, y,
|
||||||
|
hoveredOverlayUri,
|
||||||
|
hoveredOverlaySinkId,
|
||||||
|
hoveredOverVideoMuted)
|
||||||
|
{
|
||||||
callViewContextMenu.x = x
|
callViewContextMenu.x = x
|
||||||
callViewContextMenu.y = y
|
callViewContextMenu.y = y
|
||||||
|
callViewContextMenu.hoveredOverlayUri = hoveredOverlayUri
|
||||||
|
callViewContextMenu.hoveredOverlaySinkId = hoveredOverlaySinkId
|
||||||
|
callViewContextMenu.hoveredOverVideoMuted = hoveredOverVideoMuted
|
||||||
callViewContextMenu.openMenu()
|
callViewContextMenu.openMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,10 +180,16 @@ Item {
|
||||||
|
|
||||||
onTransferCallButtonClicked: openContactPicker(ContactList.TRANSFER)
|
onTransferCallButtonClicked: openContactPicker(ContactList.TRANSFER)
|
||||||
onPluginItemClicked: openPluginsMenu()
|
onPluginItemClicked: openPluginsMenu()
|
||||||
|
onScreenshotTaken: {
|
||||||
|
toastManager.instantiateToast();
|
||||||
|
}
|
||||||
onRecordCallClicked: CallAdapter.recordThisCallToggle()
|
onRecordCallClicked: CallAdapter.recordThisCallToggle()
|
||||||
onOpenSelectionWindow: {
|
onOpenSelectionWindow: {
|
||||||
SelectScreenWindowCreation.createSelectScreenWindowObject(appWindow)
|
SelectScreenWindowCreation.createSelectScreenWindowObject(appWindow)
|
||||||
SelectScreenWindowCreation.showSelectScreenWindow(callPreviewId, windowSelection)
|
SelectScreenWindowCreation.showSelectScreenWindow(callPreviewId, windowSelection)
|
||||||
}
|
}
|
||||||
|
onScreenshotButtonHoveredChanged: {
|
||||||
|
participantsLayer.screenshotButtonHovered = screenshotButtonHovered
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,12 @@ ContextMenuAutoLoader {
|
||||||
signal transferCallButtonClicked
|
signal transferCallButtonClicked
|
||||||
signal recordCallClicked
|
signal recordCallClicked
|
||||||
signal openSelectionWindow
|
signal openSelectionWindow
|
||||||
|
signal screenshotTaken
|
||||||
|
property bool screenshotButtonHovered: screenShot.itemHovered
|
||||||
|
|
||||||
|
property string hoveredOverlayUri: ""
|
||||||
|
property string hoveredOverlaySinkId: ""
|
||||||
|
property bool hoveredOverVideoMuted: true
|
||||||
|
|
||||||
property list<GeneralMenuItem> menuItems: [
|
property list<GeneralMenuItem> menuItems: [
|
||||||
GeneralMenuItem {
|
GeneralMenuItem {
|
||||||
|
@ -194,8 +200,34 @@ ContextMenuAutoLoader {
|
||||||
CallAdapter.startTimerInformation();
|
CallAdapter.startTimerInformation();
|
||||||
callInformationOverlay.open()
|
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
|
Component.onCompleted: menuItemsToLoad = menuItems
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,9 @@ RowLayout {
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|
||||||
text: shortcut
|
text: shortcut2 === "" ?
|
||||||
|
shortcut :
|
||||||
|
shortcut + " + " + shortcut2
|
||||||
font.pointSize: JamiTheme.textFontSize + 3
|
font.pointSize: JamiTheme.textFontSize + 3
|
||||||
font.weight: Font.DemiBold
|
font.weight: Font.DemiBold
|
||||||
color: JamiTheme.textColor
|
color: JamiTheme.textColor
|
||||||
|
|
|
@ -40,42 +40,52 @@ Window {
|
||||||
|
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + J"
|
shortcut: "Ctrl + J"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Open account list")
|
description: qsTr("Open account list")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + L"
|
shortcut: "Ctrl + L"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Focus conversations list")
|
description: qsTr("Focus conversations list")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + R"
|
shortcut: "Ctrl + R"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Requests list")
|
description: qsTr("Requests list")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + ↑"
|
shortcut: "Ctrl + ↑"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Previous conversation")
|
description: qsTr("Previous conversation")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + ↓"
|
shortcut: "Ctrl + ↓"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Next conversation")
|
description: qsTr("Next conversation")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + F"
|
shortcut: "Ctrl + F"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Search bar")
|
description: qsTr("Search bar")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "F11"
|
shortcut: "F11"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Full screen")
|
description: qsTr("Full screen")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + +"
|
shortcut: "Ctrl + +"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Increase font size")
|
description: qsTr("Increase font size")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + -"
|
shortcut: "Ctrl + -"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Decrease font size")
|
description: qsTr("Decrease font size")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + 0"
|
shortcut: "Ctrl + 0"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Reset font size")
|
description: qsTr("Reset font size")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,34 +95,42 @@ Window {
|
||||||
|
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + Shift + C"
|
shortcut: "Ctrl + Shift + C"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Start an audio call")
|
description: qsTr("Start an audio call")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + Shift + X"
|
shortcut: "Ctrl + Shift + X"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Start a video call")
|
description: qsTr("Start a video call")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + Shift + L"
|
shortcut: "Ctrl + Shift + L"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Clear history")
|
description: qsTr("Clear history")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + Shift + B"
|
shortcut: "Ctrl + Shift + B"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Block contact")
|
description: qsTr("Block contact")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + Shift + Delete"
|
shortcut: "Ctrl + Shift + Delete"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Remove conversation")
|
description: qsTr("Remove conversation")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Shift + Ctrl + A"
|
shortcut: "Shift + Ctrl + A"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Accept contact request")
|
description: qsTr("Accept contact request")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "↑"
|
shortcut: "↑"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Edit last message")
|
description: qsTr("Edit last message")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Esc"
|
shortcut: "Esc"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Cancel message edition")
|
description: qsTr("Cancel message edition")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,26 +140,32 @@ Window {
|
||||||
|
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + M"
|
shortcut: "Ctrl + M"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Media settings")
|
description: qsTr("Media settings")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + G"
|
shortcut: "Ctrl + G"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("General settings")
|
description: qsTr("General settings")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + I"
|
shortcut: "Ctrl + I"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Account settings")
|
description: qsTr("Account settings")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + P"
|
shortcut: "Ctrl + P"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Plugin settings")
|
description: qsTr("Plugin settings")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + Shift + N"
|
shortcut: "Ctrl + Shift + N"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Open account creation wizard")
|
description: qsTr("Open account creation wizard")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "F10"
|
shortcut: "F10"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Open keyboard shortcut table")
|
description: qsTr("Open keyboard shortcut table")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,24 +175,34 @@ Window {
|
||||||
|
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + Y"
|
shortcut: "Ctrl + Y"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Answer an incoming call")
|
description: qsTr("Answer an incoming call")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + D"
|
shortcut: "Ctrl + D"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("End call")
|
description: qsTr("End call")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "Ctrl + Shift + D"
|
shortcut: "Ctrl + Shift + D"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Decline the call request")
|
description: qsTr("Decline the call request")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "M"
|
shortcut: "M"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Mute microphone")
|
description: qsTr("Mute microphone")
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
shortcut: "V"
|
shortcut: "V"
|
||||||
|
shortcut2: ""
|
||||||
description: qsTr("Stop camera")
|
description: qsTr("Stop camera")
|
||||||
}
|
}
|
||||||
|
ListElement {
|
||||||
|
shortcut: "Ctrl"
|
||||||
|
shortcut2: qsTr("Mouse middle click")
|
||||||
|
description: qsTr("Take tile screenshot")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|
|
@ -166,7 +166,10 @@ Rectangle {
|
||||||
onTapped: function (eventPoint, button) {
|
onTapped: function (eventPoint, button) {
|
||||||
if (button === Qt.RightButton) {
|
if (button === Qt.RightButton) {
|
||||||
callOverlay.openCallViewContextMenuInPos(eventPoint.position.x,
|
callOverlay.openCallViewContextMenuInPos(eventPoint.position.x,
|
||||||
eventPoint.position.y)
|
eventPoint.position.y,
|
||||||
|
participantsLayer.hoveredOverlayUri,
|
||||||
|
participantsLayer.hoveredOverlaySinkId,
|
||||||
|
participantsLayer.hoveredOverVideoMuted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,6 +187,7 @@ Rectangle {
|
||||||
|
|
||||||
ParticipantsLayer {
|
ParticipantsLayer {
|
||||||
id: participantsLayer
|
id: participantsLayer
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
anchors.margins: 1
|
anchors.margins: 1
|
||||||
|
@ -191,9 +195,18 @@ Rectangle {
|
||||||
participantsSide: callOverlay.participantsSide
|
participantsSide: callOverlay.participantsSide
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ToastManager {
|
||||||
|
id: toastManager
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
function instantiateToast() {
|
||||||
|
instantiate(JamiStrings.screenshotTaken.arg(UtilsAdapter.getDirScreenshot()),1000,400)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LocalVideo {
|
LocalVideo {
|
||||||
id: previewRenderer
|
id: previewRenderer
|
||||||
|
|
||||||
visible: (CurrentCall.isSharing || !CurrentCall.isVideoMuted)
|
visible: (CurrentCall.isSharing || !CurrentCall.isVideoMuted)
|
||||||
&& !CurrentCall.isConference
|
&& !CurrentCall.isConference
|
||||||
|
|
||||||
|
@ -329,6 +342,11 @@ Rectangle {
|
||||||
openInCallConversation()
|
openInCallConversation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onCloseClicked: {
|
||||||
|
participantsLayer.hoveredOverlayUri = ""
|
||||||
|
participantsLayer.hoveredOverlaySinkId = ""
|
||||||
|
participantsLayer.hoveredOverVideoMuted = true
|
||||||
|
}
|
||||||
|
|
||||||
onChatButtonClicked: {
|
onChatButtonClicked: {
|
||||||
inCallMessageWebViewStack.visible ?
|
inCallMessageWebViewStack.visible ?
|
||||||
|
|
|
@ -67,6 +67,18 @@ Item {
|
||||||
property string muteAlertMessage: ""
|
property string muteAlertMessage: ""
|
||||||
property bool muteAlertActive: false
|
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: {
|
onMuteAlertActiveChanged: {
|
||||||
if (muteAlertActive) {
|
if (muteAlertActive) {
|
||||||
alertTimer.restart()
|
alertTimer.restart()
|
||||||
|
@ -94,9 +106,11 @@ Item {
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
z: -1
|
z: -1
|
||||||
color: JamiTheme.buttonTintedBlue
|
border.color: JamiTheme.buttonTintedBlue
|
||||||
|
border.width: 2
|
||||||
|
color: "transparent"
|
||||||
radius: 10
|
radius: 10
|
||||||
visible:voiceActive
|
visible: voiceActive || isScreenshotButtonHovered
|
||||||
width: participantIsActive ? mediaDistRender.contentRect.width + 2 : undefined
|
width: participantIsActive ? mediaDistRender.contentRect.width + 2 : undefined
|
||||||
height: participantIsActive ? mediaDistRender.contentRect.height + 2 : undefined
|
height: participantIsActive ? mediaDistRender.contentRect.height + 2 : undefined
|
||||||
anchors.centerIn: participantIsActive ? parent : undefined
|
anchors.centerIn: participantIsActive ? parent : undefined
|
||||||
|
@ -109,7 +123,6 @@ Item {
|
||||||
anchors.margins: 2
|
anchors.margins: 2
|
||||||
rendererId: root.sinkId
|
rendererId: root.sinkId
|
||||||
crop: !participantIsActive
|
crop: !participantIsActive
|
||||||
|
|
||||||
underlayItems: Avatar {
|
underlayItems: Avatar {
|
||||||
property real componentSize: Math.min(mediaDistRender.contentRect.width / 2, mediaDistRender.contentRect.height / 2)
|
property real componentSize: Math.min(mediaDistRender.contentRect.width / 2, mediaDistRender.contentRect.height / 2)
|
||||||
height: componentSize
|
height: componentSize
|
||||||
|
@ -140,7 +153,25 @@ Item {
|
||||||
anchors.centerIn: participantIsActive ? parent : undefined
|
anchors.centerIn: participantIsActive ? parent : undefined
|
||||||
anchors.fill: participantIsActive ? undefined : parent
|
anchors.fill: participantIsActive ? undefined : parent
|
||||||
|
|
||||||
|
TapHandler {
|
||||||
|
acceptedButtons: Qt.MiddleButton
|
||||||
|
acceptedModifiers: Qt.ControlModifier
|
||||||
|
onTapped: {
|
||||||
|
takeScreenshot()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiPointTouchArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
minimumTouchPoints: 3
|
||||||
|
onPressed: {
|
||||||
|
takeScreenshot()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
|
id: hoverIndicator
|
||||||
|
|
||||||
onPointChanged: {
|
onPointChanged: {
|
||||||
participantRect.opacity = 1
|
participantRect.opacity = 1
|
||||||
fadeOutTimer.restart()
|
fadeOutTimer.restart()
|
||||||
|
@ -164,6 +195,7 @@ Item {
|
||||||
// Participant buttons for moderation
|
// Participant buttons for moderation
|
||||||
ParticipantOverlayMenu {
|
ParticipantOverlayMenu {
|
||||||
id: overlayMenu
|
id: overlayMenu
|
||||||
|
|
||||||
visible: isMe || meModerator
|
visible: isMe || meModerator
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
@ -209,6 +241,7 @@ Item {
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: participantFootInfo
|
id: participantFootInfo
|
||||||
|
|
||||||
height: parent.height
|
height: parent.height
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
Text {
|
Text {
|
||||||
|
|
|
@ -37,6 +37,10 @@ Item {
|
||||||
property bool inLine: CallParticipantsModel.conferenceLayout === CallParticipantsModel.ONE_WITH_SMALL
|
property bool inLine: CallParticipantsModel.conferenceLayout === CallParticipantsModel.ONE_WITH_SMALL
|
||||||
property bool participantsSide
|
property bool participantsSide
|
||||||
property bool enableHideSpectators: CallParticipantsModel.count > 1 && CurrentCall.hideSpectators
|
property bool enableHideSpectators: CallParticipantsModel.count > 1 && CurrentCall.hideSpectators
|
||||||
|
property string hoveredOverlayUri: ""
|
||||||
|
property string hoveredOverlaySinkId: ""
|
||||||
|
property bool hoveredOverVideoMuted: true
|
||||||
|
property bool screenshotButtonHovered: false
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
CurrentCall.hideSelf = UtilsAdapter.getAppValue(Settings.HideSelf)
|
CurrentCall.hideSelf = UtilsAdapter.getAppValue(Settings.HideSelf)
|
||||||
|
@ -51,7 +55,10 @@ Item {
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: leftMargin_
|
anchors.leftMargin: leftMargin_
|
||||||
|
isScreenshotButtonHovered: screenshotButtonHovered && hoveredOverlaySinkId === sinkId_
|
||||||
|
opacity: screenshotButtonHovered
|
||||||
|
? hoveredOverlaySinkId !== sinkId ? 0.1 : 1
|
||||||
|
: 1
|
||||||
sinkId: sinkId_
|
sinkId: sinkId_
|
||||||
uri: uri_
|
uri: uri_
|
||||||
deviceId: deviceId_
|
deviceId: deviceId_
|
||||||
|
@ -70,6 +77,14 @@ Item {
|
||||||
participantIsModeratorMuted: audioModeratorMuted_
|
participantIsModeratorMuted: audioModeratorMuted_
|
||||||
participantHandIsRaised: isHandRaised_
|
participantHandIsRaised: isHandRaised_
|
||||||
|
|
||||||
|
onParticipantHoveredChanged: {
|
||||||
|
if (participantHovered) {
|
||||||
|
hoveredOverlayUri = overlay.uri
|
||||||
|
hoveredOverlaySinkId = overlay.sinkId
|
||||||
|
hoveredOverVideoMuted = videoMuted_
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
id: registeredNameFoundConnection
|
id: registeredNameFoundConnection
|
||||||
|
|
||||||
|
|
72
src/app/mainview/components/Toast.qml
Normal file
72
src/app/mainview/components/Toast.qml
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/app/mainview/components/ToastManager.qml
Normal file
28
src/app/mainview/components/ToastManager.qml
Normal 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});
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,24 +28,32 @@ import net.jami.Constants 1.1
|
||||||
import "../../commoncomponents"
|
import "../../commoncomponents"
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id:root
|
id: root
|
||||||
|
|
||||||
property int itemWidth
|
property int itemWidth
|
||||||
property string recordPath: AVModel.getRecordPath()
|
property string recordPath: AVModel.getRecordPath()
|
||||||
|
property string screenshotPath: UtilsAdapter.getDirScreenshot()
|
||||||
|
|
||||||
onRecordPathChanged: {
|
onRecordPathChanged: {
|
||||||
if(recordPath === "") return
|
if(recordPath === "")
|
||||||
|
return
|
||||||
|
|
||||||
if(AVModel){
|
if(AVModel) {
|
||||||
AVModel.setRecordPath(recordPath)
|
AVModel.setRecordPath(recordPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onScreenshotPathChanged: {
|
||||||
|
if (screenshotPath === "")
|
||||||
|
return
|
||||||
|
UtilsAdapter.setScreenshotPath(screenshotPath)
|
||||||
|
}
|
||||||
|
|
||||||
FolderDialog {
|
FolderDialog {
|
||||||
id: recordPathDialog
|
id: recordPathDialog
|
||||||
|
|
||||||
title: JamiStrings.selectFolder
|
title: JamiStrings.selectFolder
|
||||||
currentFolder: StandardPaths.writableLocation(StandardPaths.HomeLocation)
|
currentFolder: UtilsAdapter.getDirScreenshot()
|
||||||
options: FolderDialog.ShowDirsOnly
|
options: FolderDialog.ShowDirsOnly
|
||||||
|
|
||||||
onAccepted: {
|
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{
|
Timer{
|
||||||
id: updateRecordQualityTimer
|
id: updateRecordQualityTimer
|
||||||
|
|
||||||
|
@ -172,7 +193,7 @@ ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
text: JamiStrings.saveIn
|
text: JamiStrings.saveRecordingsTo
|
||||||
color: JamiTheme.textColor
|
color: JamiTheme.textColor
|
||||||
font.pointSize: JamiTheme.settingsFontSize
|
font.pointSize: JamiTheme.settingsFontSize
|
||||||
font.kerning: true
|
font.kerning: true
|
||||||
|
@ -199,4 +220,41 @@ ColumnLayout {
|
||||||
onClicked: recordPathDialog.open()
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -387,6 +387,22 @@ UtilsAdapter::getDirDocument()
|
||||||
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
|
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
|
QString
|
||||||
UtilsAdapter::getDirDownload()
|
UtilsAdapter::getDirDownload()
|
||||||
{
|
{
|
||||||
|
@ -425,6 +441,13 @@ UtilsAdapter::setDownloadPath(QString dir)
|
||||||
lrcInstance_->accountModel().downloadDirectory = dir + "/";
|
lrcInstance_->accountModel().downloadDirectory = dir + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UtilsAdapter::setScreenshotPath(QString dir)
|
||||||
|
{
|
||||||
|
setAppValue(Settings::Key::ScreenshotPath, dir);
|
||||||
|
lrcInstance_->accountModel().screenshotDirectory = dir + QDir::separator();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UtilsAdapter::monitor(const bool& continuous)
|
UtilsAdapter::monitor(const bool& continuous)
|
||||||
{
|
{
|
||||||
|
|
|
@ -107,9 +107,11 @@ public:
|
||||||
Q_INVOKABLE QVariant getAppValue(const Settings::Key key);
|
Q_INVOKABLE QVariant getAppValue(const Settings::Key key);
|
||||||
Q_INVOKABLE void setAppValue(const Settings::Key key, const QVariant& value);
|
Q_INVOKABLE void setAppValue(const Settings::Key key, const QVariant& value);
|
||||||
Q_INVOKABLE QString getDirDocument();
|
Q_INVOKABLE QString getDirDocument();
|
||||||
|
Q_INVOKABLE QString getDirScreenshot();
|
||||||
Q_INVOKABLE QString getDirDownload();
|
Q_INVOKABLE QString getDirDownload();
|
||||||
Q_INVOKABLE void setRunOnStartUp(bool state);
|
Q_INVOKABLE void setRunOnStartUp(bool state);
|
||||||
Q_INVOKABLE void setDownloadPath(QString dir);
|
Q_INVOKABLE void setDownloadPath(QString dir);
|
||||||
|
Q_INVOKABLE void setScreenshotPath(QString dir);
|
||||||
Q_INVOKABLE void monitor(const bool& continuous);
|
Q_INVOKABLE void monitor(const bool& continuous);
|
||||||
Q_INVOKABLE void clearInteractionsCache(const QString& accountId, const QString& convUid);
|
Q_INVOKABLE void clearInteractionsCache(const QString& accountId, const QString& convUid);
|
||||||
Q_INVOKABLE QVariantMap supportedLang();
|
Q_INVOKABLE QVariantMap supportedLang();
|
||||||
|
|
|
@ -117,6 +117,13 @@ VideoProvider::frame(const QString& id)
|
||||||
|
|
||||||
QString
|
QString
|
||||||
VideoProvider::captureVideoFrame(const QString& id)
|
VideoProvider::captureVideoFrame(const QString& id)
|
||||||
|
{
|
||||||
|
auto img = captureRawVideoFrame(id);
|
||||||
|
return Utils::byteArrayToBase64String(Utils::QImageToByteArray(img));
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage
|
||||||
|
VideoProvider::captureRawVideoFrame(const QString& id)
|
||||||
{
|
{
|
||||||
QMutexLocker framesLk(&framesObjsMutex_);
|
QMutexLocker framesLk(&framesObjsMutex_);
|
||||||
if (auto* videoFrame = frame(id)) {
|
if (auto* videoFrame = frame(id)) {
|
||||||
|
@ -127,7 +134,7 @@ VideoProvider::captureVideoFrame(const QString& id)
|
||||||
videoFrame->height(),
|
videoFrame->height(),
|
||||||
videoFrame->bytesPerLine(0),
|
videoFrame->bytesPerLine(0),
|
||||||
imageFormat);
|
imageFormat);
|
||||||
return Utils::byteArrayToBase64String(Utils::QImageToByteArray(img));
|
return img;
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
Q_INVOKABLE void registerSink(const QString& id, QVideoSink* obj);
|
Q_INVOKABLE void registerSink(const QString& id, QVideoSink* obj);
|
||||||
Q_INVOKABLE void unregisterSink(QVideoSink* obj);
|
Q_INVOKABLE void unregisterSink(QVideoSink* obj);
|
||||||
Q_INVOKABLE QString captureVideoFrame(const QString& id);
|
Q_INVOKABLE QString captureVideoFrame(const QString& id);
|
||||||
|
Q_INVOKABLE QImage captureRawVideoFrame(const QString& id);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void onRendererStarted(const QString& id, const QSize& size);
|
void onRendererStarted(const QString& id, const QSize& size);
|
||||||
|
|
|
@ -73,6 +73,7 @@ public:
|
||||||
* Should contains the full directory with the end marker (/ on linux for example)
|
* Should contains the full directory with the end marker (/ on linux for example)
|
||||||
*/
|
*/
|
||||||
QString downloadDirectory;
|
QString downloadDirectory;
|
||||||
|
QString screenshotDirectory;
|
||||||
/**
|
/**
|
||||||
* Accept transfer from trusted contacts
|
* Accept transfer from trusted contacts
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Reference in a new issue