import QtQuick import QtQuick.Layouts import QtQuick.Effects import QtQuick.Controls.Basic as Control import Linphone import EnumsToStringCpp import UtilsCpp import SettingsCpp import DesktopToolsCpp import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle AbstractWindow { id: mainWindow flags: Qt.Window minimumWidth: Math.round(1020 * DefaultStyle.dp) minimumHeight: Math.round(700 * DefaultStyle.dp) // modality: Qt.WindowModal property CallGui call property ConferenceGui conference: call && call.core.conference || null property bool isConference: call ? call.core.isConference : false property int conferenceLayout: call && call.core.conferenceVideoLayout || 0 property bool localVideoEnabled: call && call.core.localVideoEnabled property bool remoteVideoEnabled: call && call.core.remoteVideoEnabled property bool callTerminatedByUser: false property var callState: call ? call.core.state : LinphoneEnums.CallState.Idle property var transferState: call && call.core.transferState onCallStateChanged: { if (callState === LinphoneEnums.CallState.Connected) { if (middleItemStackView.currentItem.objectName != "inCallItem") { middleItemStackView.replace(inCallItem) bottomButtonsLayout.visible = true } if (call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp && !mainWindow.isConference && (!call.core.tokenVerified || call.core.isMismatch)) { zrtpValidation.open() } } else if (callState === LinphoneEnums.CallState.Error || callState === LinphoneEnums.CallState.End) { zrtpValidation.close() callEnded(call) } } onTransferStateChanged: { console.log("Transfer state:", transferState) if (mainWindow.transferState === LinphoneEnums.CallState.OutgoingInit) { var callsWin = UtilsCpp.getCallsWindow() if (!callsWin) return //: "Transfert en cours, veuillez patienter" callsWin.showLoadingPopup(qsTr("call_transfer_in_progress_toast")) } else if (mainWindow.transferState === LinphoneEnums.CallState.Error || mainWindow.transferState === LinphoneEnums.CallState.End || mainWindow.transferState === LinphoneEnums.CallState.Released || mainWindow.transferState === LinphoneEnums.CallState.Connected) { var callsWin = UtilsCpp.getCallsWindow() callsWin.closeLoadingPopup() if (transferState === LinphoneEnums.CallState.Error) UtilsCpp.showInformationPopup( qsTr("information_popup_error_title"), //: "Le transfert d'appel a échoué" qsTr("call_transfer_failed_toast"), false, mainWindow) else if (transferState === LinphoneEnums.CallState.Connected) { var mainWin = UtilsCpp.getMainWindow() UtilsCpp.smartShowWindow(mainWin) mainWin.transferCallSucceed() } } } onClosing: close => { DesktopToolsCpp.screenSaverStatus = true if (callsModel.haveCall) { close.accepted = false terminateAllCallsDialog.open() } if (middleItemStackView.currentItem.objectName === "waitingRoom") middleItemStackView.replace(inCallItem) } function changeLayout(layoutIndex) { if (layoutIndex == 0) { console.log("Set Grid layout") call.core.lSetConferenceVideoLayout( LinphoneEnums.ConferenceLayout.Grid) } else if (layoutIndex == 1) { console.log("Set AS layout") call.core.lSetConferenceVideoLayout( LinphoneEnums.ConferenceLayout.ActiveSpeaker) } else { console.log("Set audio-only layout") call.core.lSetConferenceVideoLayout( LinphoneEnums.ConferenceLayout.AudioOnly) } } function endCall(callToFinish) { if (callToFinish) callToFinish.core.lTerminate() else { if (!callsModel.haveCall) UtilsCpp.closeCallsWindow() } // var mainWin = UtilsCpp.getMainWindow() // mainWin.goToCallHistory() } function callEnded(call) { if (call && call.core.state === LinphoneEnums.CallState.Error) { middleItemStackView.replace(inCallItem) } if (!callsModel.haveCall) { if (call && call.core.isConference) UtilsCpp.closeCallsWindow() else { bottomButtonsLayout.setButtonsEnabled(false) autoCloseWindow.restart() } } else { if (middleItemStackView.currentItem.objectName === "waitingRoom") { middleItemStackView.replace(inCallItem) } mainWindow.call = callsModel.currentCall } } signal setUpConferenceRequested(ConferenceInfoGui conferenceInfo) function setupConference(conferenceInfo) { middleItemStackView.replace(waitingRoom) setUpConferenceRequested(conferenceInfo) } function joinConference(uri, options) { if (uri.length === 0) UtilsCpp.showInformationPopup(qsTr("information_popup_error_title"), //: "La conférence n'a pas pu démarrer en raison d'une erreur d'uri." qsTr("conference_error_empty_uri"),mainWindow) else { UtilsCpp.createCall(uri, options) } } function cancelJoinConference() { if (!callsModel.haveCall) { UtilsCpp.closeCallsWindow() } else { mainWindow.call = callsModel.currentCall } middleItemStackView.replace(inCallItem) } function cancelAfterJoin() { endCall(mainWindow.call) } Connections { enabled: !!mainWindow.call target: mainWindow.call && mainWindow.call.core function onSecurityUpdated() { if (mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp) { if (call.core.tokenVerified) { zrtpValidation.close() zrtpValidationToast.open() } else { zrtpValidation.open() } } else { zrtpValidation.close() } } function onTokenVerified() { if (!zrtpValidation.isTokenVerified) { zrtpValidation.securityError = true } else zrtpValidation.close() } } Timer { id: autoCloseWindow interval: mainWindow.callTerminatedByUser ? 1500 : 2500 onTriggered: { UtilsCpp.closeCallsWindow() } } Dialog { id: terminateAllCallsDialog onAccepted: { mainWindow.callTerminatedByUser = true call.core.lTerminateAllCalls() } width: Math.round(278 * DefaultStyle.dp) //: "Terminer tous les appels en cours ?" title: qsTr("call_close_window_dialog_title") //: "La fenêtre est sur le point d'être fermée. Cela terminera tous les appels en cours." text: qsTr("call_close_window_dialog_message") } CallProxy { id: callsModel sourceModel: AppCpp.calls onCurrentCallChanged: { if (currentCall) { mainWindow.call = currentCall } } onHaveCallChanged: { if (!haveCall) { mainWindow.callEnded() } } } component BottomButton: Button { id: bottomButton required property string enabledIcon property string disabledIcon enabled: call != undefined leftPadding: 0 rightPadding: 0 topPadding: 0 bottomPadding: 0 checkable: true background: Rectangle { anchors.fill: parent color: bottomButton.enabled ? disabledIcon ? DefaultStyle.grey_500 : bottomButton.pressed || bottomButton.checked ? DefaultStyle.main2_400 : DefaultStyle.grey_500 : DefaultStyle.grey_600 radius: Math.round(71 * DefaultStyle.dp) } icon.source: disabledIcon && bottomButton.checked ? disabledIcon : enabledIcon icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) contentImageColor: DefaultStyle.grey_0 } ZrtpAuthenticationDialog { id: zrtpValidation call: mainWindow.call modal: true closePolicy: Popup.NoAutoClose } Timer { id: autoCloseZrtpToast interval: 4000 onTriggered: { zrtpValidationToast.y = -zrtpValidationToast.height * 2 } } Control.Control { id: zrtpValidationToast // width: Math.round(269 * DefaultStyle.dp) y: -height * 2 z: 1 topPadding: Math.round(8 * DefaultStyle.dp) bottomPadding: Math.round(8 * DefaultStyle.dp) leftPadding: Math.round(50 * DefaultStyle.dp) rightPadding: Math.round(50 * DefaultStyle.dp) anchors.horizontalCenter: parent.horizontalCenter clip: true function open() { if (mainWindow.isConference) return y = headerItem.height / 2 autoCloseZrtpToast.restart() } Behavior on y { NumberAnimation { duration: 1000 } } background: Rectangle { anchors.fill: parent color: DefaultStyle.grey_0 border.color: DefaultStyle.info_500_main border.width: Math.max(Math.round(1 * DefaultStyle.dp), 1) radius: Math.round(50 * DefaultStyle.dp) } contentItem: RowLayout { // anchors.centerIn: parent Image { source: AppIcons.trusted Layout.preferredWidth: Math.round(24 * DefaultStyle.dp) Layout.preferredHeight: Math.round(24 * DefaultStyle.dp) fillMode: Image.PreserveAspectFit Layout.fillWidth: true } Text { color: DefaultStyle.info_500_main //: "Appareil authentifié" text: qsTr("call_can_be_trusted_toast") Layout.fillWidth: true font { pixelSize: Math.round(14 * DefaultStyle.dp) } } } } /************************* CONTENT ********************************/ Rectangle { anchors.fill: parent color: DefaultStyle.grey_900 Keys.onEscapePressed: { if (mainWindow.visibility == Window.FullScreen) mainWindow.showNormal() } ColumnLayout { anchors.fill: parent spacing: Math.round(10 * DefaultStyle.dp) anchors.bottomMargin: Math.round(10 * DefaultStyle.dp) anchors.topMargin: Math.round(10 * DefaultStyle.dp) Item { id: headerItem Layout.margins: Math.round(10 * DefaultStyle.dp) Layout.leftMargin: Math.round(20 * DefaultStyle.dp) Layout.fillWidth: true Layout.minimumHeight: Math.round(25 * DefaultStyle.dp) RowLayout { anchors.left: parent.left anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter spacing: Math.round(10 * DefaultStyle.dp) RowLayout { spacing: Math.round(10 * DefaultStyle.dp) EffectImage { id: callStatusIcon Layout.preferredWidth: Math.round(30 * DefaultStyle.dp) Layout.preferredHeight: Math.round(30 * DefaultStyle.dp) // TODO : change with broadcast or meeting icon when available imageSource: !mainWindow.call ? AppIcons.meeting : (mainWindow.callState === LinphoneEnums.CallState.End || mainWindow.callState === LinphoneEnums.CallState.Released) ? AppIcons.endCall : (mainWindow.callState === LinphoneEnums.CallState.Paused || mainWindow.callState === LinphoneEnums.CallState.PausedByRemote) ? AppIcons.pause : mainWindow.conference ? AppIcons.usersThree : mainWindow.call.core.dir === LinphoneEnums.CallDir.Outgoing ? AppIcons.arrowUpRight : AppIcons.arrowDownLeft colorizationColor: !mainWindow.call || mainWindow.call.core.paused || mainWindow.callState === LinphoneEnums.CallState.Paused || mainWindow.callState === LinphoneEnums.CallState.PausedByRemote || mainWindow.callState === LinphoneEnums.CallState.End || mainWindow.callState === LinphoneEnums.CallState.Released || mainWindow.conference ? DefaultStyle.danger_500main : mainWindow.call.core.dir === LinphoneEnums.CallDir.Outgoing ? DefaultStyle.info_500_main : DefaultStyle.success_500main onColorizationColorChanged: { callStatusIcon.active = !callStatusIcon.active callStatusIcon.active = !callStatusIcon.active } } ColumnLayout { spacing: Math.round(6 * DefaultStyle.dp) RowLayout { spacing: Math.round(10 * DefaultStyle.dp) Text { id: callStatusText property string remoteName: mainWindow.call ? qsTr("call_dir").arg(EnumsToStringCpp.dirToString(mainWindow.call.core.dir)) : "" Connections { target: mainWindow onCallStateChanged: { if (mainWindow.callState === LinphoneEnums.CallState.Connected || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning) callStatusText.remoteName = mainWindow.call.core.remoteName } } text: (mainWindow.callState === LinphoneEnums.CallState.End || mainWindow.callState === LinphoneEnums.CallState.Released) //: Appel terminé ? qsTr("call_ended") : mainWindow.call && (mainWindow.call.core.paused) ? (mainWindow.conference //: Meeting paused ? qsTr("conference_paused") : mainWindow.callState === LinphoneEnums.CallState.PausedByRemote //: Call paused by remote ? qsTr("call_paused_by_remote") //: Call paused : qsTr("call_paused")) : mainWindow.conference ? mainWindow.conference.core.subject : remoteName color: DefaultStyle.grey_0 font { pixelSize: Typography.h3.pixelSize weight: Typography.h3.weight } } Rectangle { visible: mainWindow.call && (mainWindow.callState === LinphoneEnums.CallState.Connected || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning) Layout.fillHeight: true Layout.topMargin: Math.round(10 * DefaultStyle.dp) Layout.bottomMargin: Math.round(2 * DefaultStyle.dp) Layout.preferredWidth: Math.round(2 * DefaultStyle.dp) color: DefaultStyle.grey_0 } Text { text: mainWindow.call ? UtilsCpp.formatElapsedTime(mainWindow.call.core.duration) : "" color: DefaultStyle.grey_0 font { pixelSize: Typography.h3.pixelSize weight: Typography.h3.weight } visible: mainWindow.callState === LinphoneEnums.CallState.Connected || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning } Text { Layout.leftMargin: Math.round(14 * DefaultStyle.dp) id: conferenceDate text: mainWindow.conferenceInfo ? mainWindow.conferenceInfo.core.getStartEndDateString() : "" color: DefaultStyle.grey_0 font { pixelSize: Typography.p1.pixelSize weight: Typography.p1.weight capitalization: Font.Capitalize } } } RowLayout { id: securityStateLayout spacing: Math.round(5 * DefaultStyle.dp) visible: false Connections { target: mainWindow function onCallStateChanged() { if (mainWindow.callState === LinphoneEnums.CallState.Connected) securityStateLayout.visible = true else if (mainWindow.callState === LinphoneEnums.CallState.End || mainWindow.callState === LinphoneEnums.CallState.Released) securityStateLayout.visible = false } } BusyIndicator { //: Waiting for encryption visible: encryptionStatusText.text === qsTr("call_waiting_for_encryption_info") Layout.preferredWidth: Math.round(15 * DefaultStyle.dp) Layout.preferredHeight: Math.round(15 * DefaultStyle.dp) indicatorColor: DefaultStyle.grey_0 } EffectImage { Layout.preferredWidth: Math.round(15 * DefaultStyle.dp) Layout.preferredHeight: Math.round(15 * DefaultStyle.dp) colorizationColor: mainWindow.call ? mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Srtp ? DefaultStyle.info_500_main : mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp ? mainWindow.call.core.isMismatch || !mainWindow.call.core.tokenVerified ? DefaultStyle.warning_600 : DefaultStyle.info_500_main : DefaultStyle.grey_0 : "transparent" visible: mainWindow.call imageSource: mainWindow.call ? mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Srtp ? AppIcons.lockSimple : mainWindow.call && mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp ? mainWindow.call.core.isMismatch || !mainWindow.call.core.tokenVerified ? AppIcons.warningCircle : AppIcons.lockKey : AppIcons.lockSimpleOpen : "" } Text { id: encryptionStatusText text: mainWindow.conference ? qsTr("call_srtp_point_to_point_encrypted") : mainWindow.call ? mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Srtp //: Appel chiffré de point à point ? qsTr("call_srtp_point_to_point_encrypted") : mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp ? mainWindow.call.core.isMismatch || !mainWindow.call.core.tokenVerified //: Vérification nécessaire ? qsTr("call_zrtp_sas_validation_required") //: Appel chiffré de bout en bout : qsTr("call_zrtp_end_to_end_encrypted") : mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.None //: "Appel non chiffré" ? qsTr("call_not_encrypted") : qsTr("call_waiting_for_encryption_info") : "" color: mainWindow.conference || mainWindow.call?.core.encryption === LinphoneEnums.MediaEncryption.Srtp ? DefaultStyle.info_500_main : mainWindow.call ? mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp ? mainWindow.call.core.isMismatch || !mainWindow.call.core.tokenVerified ? DefaultStyle.warning_600 : DefaultStyle.info_500_main : DefaultStyle.grey_0 : DefaultStyle.grey_0 font { pixelSize: Math.round(12 * DefaultStyle.dp) weight: Math.round(400 * DefaultStyle.dp) } MouseArea { anchors.fill: parent hoverEnabled: true cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor onClicked: { if (rightPanel.visible && rightPanel.contentLoader.item.objectName === "encryptionPanel") rightPanel.visible = false else { rightPanel.visible = true rightPanel.replace(encryptionPanel) } } } } Item { Layout.fillWidth: true } } } } Item { Layout.fillWidth: true } EffectImage { Layout.preferredWidth: Math.round(32 * DefaultStyle.dp) Layout.preferredHeight: Math.round(32 * DefaultStyle.dp) Layout.rightMargin: Math.round(30 * DefaultStyle.dp) property int quality: mainWindow.call ? mainWindow.call.core.quality : 0 imageSource: quality >= 4 ? AppIcons.cellSignalFull : quality >= 3 ? AppIcons.cellSignalMedium : quality >= 2 ? AppIcons.cellSignalLow : AppIcons.cellSignalNone colorizationColor: DefaultStyle.grey_0 MouseArea { anchors.fill: parent hoverEnabled: true cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor onClicked: { if (rightPanel.visible && rightPanel.contentLoader.item.objectName === "statsPanel") rightPanel.visible = false else { rightPanel.visible = true rightPanel.replace(statsPanel) } } } } } Control.Control { visible: mainWindow.call ? !!mainWindow.conference ? mainWindow.conference.core.isRecording : (mainWindow.call.core.recording || mainWindow.call.core.remoteRecording) : false anchors.centerIn: parent leftPadding: Math.round(14 * DefaultStyle.dp) rightPadding: Math.round(14 * DefaultStyle.dp) topPadding: Math.round(6 * DefaultStyle.dp) bottomPadding: Math.round(6 * DefaultStyle.dp) background: Rectangle { anchors.fill: parent color: DefaultStyle.grey_500 radius: Math.round(10 * DefaultStyle.dp) } contentItem: RowLayout { spacing: Math.round(85 * DefaultStyle.dp) RowLayout { spacing: Math.round(15 * DefaultStyle.dp) EffectImage { imageSource: AppIcons.recordFill colorizationColor: DefaultStyle.danger_500main Layout.preferredWidth: Math.round(24 * DefaultStyle.dp) Layout.preferredHeight: Math.round(24 * DefaultStyle.dp) } Text { color: DefaultStyle.danger_500main font.pixelSize: Math.round(14 * DefaultStyle.dp) text: mainWindow.call ? mainWindow.call.core.recording ? mainWindow.conference //: "Vous enregistrez la réunion" ? qsTr("conference_user_is_recording") //: "Vous enregistrez l'appel" : qsTr("call_user_is_recording") : mainWindow.conference //: "Un participant enregistre la réunion" ? qsTr("conference_remote_is_recording") //: "%1 enregistre l'appel" : qsTr("call_remote_recording").arg(mainWindow.call.core.remoteName) : "" } } BigButton { visible: mainWindow.call && mainWindow.call.core.recording //: "Arrêter l'enregistrement" text: qsTr("call_stop_recording") style: ButtonStyle.main onPressed: mainWindow.call.core.lStopRecording() } } } } RowLayout { Layout.fillWidth: true Layout.fillHeight: true spacing: Math.round(23 * DefaultStyle.dp) Control.StackView { id: middleItemStackView initialItem: inCallItem Layout.fillWidth: true Layout.fillHeight: true } CallSettingsPanel { id: rightPanel Layout.fillHeight: true Layout.rightMargin: Math.round(20 * DefaultStyle.dp) Layout.preferredWidth: Math.round(393 * DefaultStyle.dp) Layout.topMargin: Math.round(10 * DefaultStyle.dp) property int currentIndex: 0 visible: false onVisibleChanged: if(!visible) contentLoader.sourceComponent = null function replace(id) { rightPanel.customHeaderButtons = null contentLoader.sourceComponent = id } headerStack.currentIndex: 0 headerValidateButtonText: qsTr("add") // Do not consider padding for chat Binding on topPadding { when: rightPanel.contentLoader.item && rightPanel.contentLoader.item.objectName === "chatPanel" value: 0 restoreMode: Binding.RestoreBindingOrValue } Binding on leftPadding { when: rightPanel.contentLoader.item && rightPanel.contentLoader.item.objectName === "chatPanel" value: 0 restoreMode: Binding.RestoreBindingOrValue } Binding on rightPadding { when: rightPanel.contentLoader.item && rightPanel.contentLoader.item.objectName == "chatPanel" value: 0 restoreMode: Binding.RestoreBindingOrValue } Connections { target: rightPanel.contentLoader function onItemChanged() { if (rightPanel.contentLoader.item) { if (rightPanel.contentLoader.item.objectName === "callTransferPanel") { //: "Transférer %1 à…" rightPanel.headerTitleText = qsTr("call_transfer_current_call_title").arg(mainWindow.call.core.remoteName) } else if (rightPanel.contentLoader.item.objectName === "newCallPanel") { //: "Nouvel appel" rightPanel.headerTitleText = qsTr("call_action_start_new_call") } else if (rightPanel.contentLoader.item.objectName === "dialerPanel") { //: "Pavé numérique" rightPanel.headerTitleText = qsTr("call_action_show_dialer") } else if (rightPanel.contentLoader.item.objectName === "changeLayoutPanel") { //: "Modifier la disposition" rightPanel.headerTitleText = qsTr("call_action_change_layout") } else if (rightPanel.contentLoader.item.objectName === "callListPanel") { //: "Liste d'appel" rightPanel.headerTitleText = qsTr("call_action_go_to_calls_list") } else if (rightPanel.contentLoader.item.objectName === "chatPanel") { rightPanel.headerTitleText = "" } else if (rightPanel.contentLoader.item.objectName === "settingsPanel") { //: "Paramètres" rightPanel.headerTitleText = qsTr("call_action_go_to_settings") } else if (rightPanel.contentLoader.item.objectName === "screencastPanel") { //: "Partage de votre écran" rightPanel.headerTitleText = qsTr("conference_action_screen_sharing") } else if (rightPanel.contentLoader.item.objectName === "encryptionPanel") { //: Chiffrement rightPanel.headerTitleText = qsTr("call_encryption_title") } else if (rightPanel.contentLoader.item.objectName === "statsPanel") { //: Statistiques rightPanel.headerTitleText = qsTr("call_stats_title") } } if (!rightPanel.contentLoader.item || rightPanel.contentLoader.item.objectName !== "participantListPanel") rightPanel.headerStack.currentIndex = 0 if (!rightPanel.contentLoader.item || rightPanel.contentLoader.item.objectName !== "callTransferPanel") transferCallButton.checked = false if (!rightPanel.contentLoader.item || rightPanel.contentLoader.item.objectName !== "newCallPanel") newCallButton.checked = false if (!rightPanel.contentLoader.item || rightPanel.contentLoader.item.objectName !== "callListPanel") callListButton.checked = false if (!rightPanel.contentLoader.item || rightPanel.contentLoader.item.objectName !== "screencastPanel") screencastPanelButton.checked = false if (!rightPanel.contentLoader.item || rightPanel.contentLoader.item.objectName !== "chatPanel") chatPanelButton.checked = false if (!rightPanel.contentLoader.item || rightPanel.contentLoader.item.objectName !== "participantListPanel") participantListButton.checked = false } } // Binding on rightPadding { // when: rightPanel.contentLoader.item && rightPanel.contentLoader.item.objectName == "participantListView" // value: Math.round(10 * DefaultStyle.dp) // restoreMode: Binding.RestoreBindingOrValue // } Item { id: numericPadContainer anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right height: childrenRect.height } } } Component { id: callTransferPanel Control.Control { objectName: "callTransferPanel" width: parent.width NewCallForm { id: newCallForm width: parent.width height: rightPanel.contentItemHeight Keys.onEscapePressed: event => { rightPanel.visible = false event.accepted = true } groupCallVisible: false displayCurrentCalls: true searchBarColor: DefaultStyle.grey_0 searchBarBorderColor: DefaultStyle.grey_200 onContactClicked: contact => { var callsWin = UtilsCpp.getCallsWindow() if (contact) //: "Confirmer le transfert" callsWin.showConfirmationLambdaPopup(qsTr("call_transfer_confirm_dialog_tittle"), //: "Vous allez transférer %1 à %2." qsTr("call_transfer_confirm_dialog_message").arg(mainWindow.call.core.remoteName).arg(contact.core.fullName), "", function (confirmed) { if (confirmed) { mainWindow.transferCallToContact(mainWindow.call,contact,newCallForm) } }) } onTransferCallToAnotherRequested: dest => { var callsWin = UtilsCpp.getCallsWindow() console.log("transfer to",dest) callsWin.showConfirmationLambdaPopup(qsTr("call_transfer_confirm_dialog_tittle"), qsTr("call_transfer_confirm_dialog_message").arg(mainWindow.call.core.remoteName).arg(dest.core.remoteName),"", function (confirmed) { if (confirmed) { mainWindow.call.core.lTransferCallToAnother(dest.core.remoteAddress) } }) } numPadPopup: numPadPopup NumericPadPopup { id: numPadPopup parent: numericPadContainer width: parent.width roundedBottom: true lastRowVisible: false visible: false leftPadding: Math.round(40 * DefaultStyle.dp) rightPadding: Math.round(40 * DefaultStyle.dp) topPadding: Math.round(41 * DefaultStyle.dp) bottomPadding: Math.round(18 * DefaultStyle.dp) Component.onCompleted: parent.height = height } } } } Component { id: newCallPanel Control.Control { objectName: "newCallPanel" width: parent.width NewCallForm { id: newCallForm width: parent.width height: rightPanel.contentItemHeight groupCallVisible: false searchBarColor: DefaultStyle.grey_0 searchBarBorderColor: DefaultStyle.grey_200 numPadPopup: numericPad onContactClicked: contact => { mainWindow.startCallWithContact( contact, false, rightPanel) } Connections { target: mainWindow function onCallChanged() { if (newCallForm.Control.StackView.status === Control.StackView.Active) rightPanel.visible = false } } NumericPadPopup { id: numericPad width: parent.width parent: numericPadContainer roundedBottom: true visible: newCallForm.searchBar.numericPadButton.checked leftPadding: Math.round(40 * DefaultStyle.dp) rightPadding: Math.round(40 * DefaultStyle.dp) topPadding: Math.round(41 * DefaultStyle.dp) bottomPadding: Math.round(18 * DefaultStyle.dp) onLaunchCall: { rightPanel.visible = false UtilsCpp.createCall(newCallForm.searchBar.text) } Component.onCompleted: parent.height = height } } } } Component { id: dialerPanel Control.Control { id: dialerPanelContent objectName: "dialerPanel" width: parent.width Keys.onEscapePressed: event => { rightPanel.visible = false event.accepted = true } FocusScope { width: parent.width height: rightPanel.contentItemHeight ColumnLayout { anchors.fill: parent spacing: Math.round(41 * DefaultStyle.dp) Item{Layout.fillHeight: true} SearchBar { id: searchBar height: Math.round(45 * DefaultStyle.dp) magnifierVisible: false color: DefaultStyle.grey_0 borderColor: DefaultStyle.grey_200 placeholderText: "" numericPadPopup: numPad numericPadButton.visible: false enabled: false } NumericPad { id: numPad Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom Layout.bottomMargin: Math.round(18 * DefaultStyle.dp) currentCall: callsModel.currentCall lastRowVisible: false onLaunchCall: { UtilsCpp.createCall(dialerTextInput.text) } Component.onCompleted: parent.height = height } } } } } Component { id: changeLayoutPanel ChangeLayoutForm { objectName: "changeLayoutPanel" width: parent.width Keys.onEscapePressed: event => { rightPanel.visible = false event.accepted = true } call: mainWindow.call onChangeLayoutRequested: index => { mainWindow.changeLayout(index) } } } Component { id: callListPanel ColumnLayout { objectName: "callListPanel" Keys.onEscapePressed: event => { rightPanel.visible = false event.accepted = true } spacing: 0 Component { id: mergeCallPopupButton PopupButton { visible: callsModel.count >= 2 id: popupbutton popup.contentItem: IconLabelButton { icon.source: AppIcons.arrowsMerge icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) //: call_action_merge_calls text: qsTr("Merger tous les appels") textSize: Math.round(14 * DefaultStyle.dp) onClicked: { callsModel.lMergeAll() popupbutton.close() } } } } RoundedPane { Layout.fillWidth: true Layout.maximumHeight: rightPanel.height visible: callList.contentHeight > 0 leftPadding: Math.round(16 * DefaultStyle.dp) rightPadding: Math.round(6 * DefaultStyle.dp) topPadding: Math.round(15 * DefaultStyle.dp) bottomPadding: Math.round(16 * DefaultStyle.dp) Layout.topMargin: Math.round(15 * DefaultStyle.dp) Layout.bottomMargin: Math.round(16 * DefaultStyle.dp) Layout.leftMargin: Math.round(16 * DefaultStyle.dp) Layout.rightMargin: Math.round(16 * DefaultStyle.dp) contentItem: CallListView { id: callList } } Item { Layout.fillHeight: true } Connections { target: rightPanel.contentLoader function onItemChanged() { if (rightPanel.contentLoader.item.objectName === "callListPanel") { rightPanel.customHeaderButtons = mergeCallPopupButton.createObject(rightPanel) } } } } } Component { id: chatPanel Control.Control { objectName: "chatPanel" width: parent.width SelectedChatView { id: chatView width: parent.width height: rightPanel.contentItemHeight Keys.onEscapePressed: event => { rightPanel.visible = false event.accepted = true } call: mainWindow.call property var chatObj: UtilsCpp.getCurrentCallChat(mainWindow.call) chat: chatObj ? chatObj.value : null } Connections { target: rightPanel.contentLoader function onItemChanged() { if (rightPanel.contentLoader.item.objectName === "chatPanel") { rightPanel.customHeaderButtons = chatView.callHeaderContent } } } } } Component { id: settingsPanel MultimediaSettings { id: inSettingsPanel objectName: "settingsPanel" Keys.onEscapePressed: event => { rightPanel.visible = false event.accepted = true } call: mainWindow.call height: childrenRect.height width: parent.width } } Component { id: screencastPanel Control.Control { objectName: "screencastPanel" width: parent.width height: contentChildren.height Keys.onEscapePressed: event => { rightPanel.visible = false event.accepted = true } contentItem: ScreencastSettings { id: screencastsettings anchors.topMargin: Math.round(16 * DefaultStyle.dp) width: parent.width call: mainWindow.call } } } Component { id: participantListPanel Control.Control { width: parent.width objectName: "participantListPanel" Keys.onEscapePressed: event => { rightPanel.visible = false event.accepted = true } Control.StackView { id: participantsStack width: parent.width height: rightPanel.contentItemHeight // anchors.fill: parent // anchors.bottomMargin: Math.round(16 * DefaultStyle.dp) // anchors.leftMargin: Math.round(17 * DefaultStyle.dp) // anchors.rightMargin: Math.round(17 * DefaultStyle.dp) initialItem: participantListComp onCurrentItemChanged: rightPanel.headerStack.currentIndex = currentItem.Control.StackView.index property list selectedParticipants Connections { target: rightPanel function onReturnRequested() { participantsStack.pop() } } Component { id: participantListComp ParticipantListView { id: participantList objectName: "participantListView" call: mainWindow.call height: contentHeight width: parent.width rightMargin: 0 Component { id: headerbutton PopupButton { popup.contentItem: IconLabelButton { icon.source: AppIcons.shareNetwork //: Partager le lien de la réunion text: qsTr("conference_share_link_title") onClicked: { UtilsCpp.copyToClipboard(mainWindow.conference ? mainWindow.conference.core.uri : mainWindow.call.core.remoteAddress) //: Copié showInformationPopup(qsTr("copied"), //: Le lien de la réunion a été copié dans le presse-papier qsTr("information_popup_meeting_address_copied_to_clipboard"),true) } } } } onVisibleChanged: if (visible) { rightPanel.customHeaderButtons = headerbutton.createObject(rightPanel) //: "Participants (%1)" rightPanel.headerTitleText = qsTr("conference_participants_list_title").arg(count) } onAddParticipantRequested: participantsStack.push(addParticipantComp) onCountChanged: { rightPanel.headerTitleText = qsTr("conference_participants_list_title").arg(count) } Connections { target: participantsStack function onCurrentItemChanged() { if (participantsStack.currentItem == participantList) rightPanel.headerTitleText = qsTr("conference_participants_list_title").arg(participantList.count) } } Connections { target: rightPanel function onValidateRequested() { participantList.model.addAddresses(participantsStack.selectedParticipants) participantsStack.pop() } } } } Component { id: addParticipantComp AddParticipantsForm { id: addParticipantLayout // height: childrenRect.height // width: parent.width searchBarColor: DefaultStyle.grey_0 searchBarBorderColor: DefaultStyle.grey_200 onSelectedParticipantsCountChanged: { rightPanel.headerSubtitleText = qsTr("group_call_participant_selected", '', selectedParticipantsCount).arg(selectedParticipantsCount) participantsStack.selectedParticipants = selectedParticipants } Connections { target: participantsStack function onCurrentItemChanged() { if (participantsStack.currentItem == addParticipantLayout) { rightPanel.headerTitleText = qsTr("meeting_schedule_add_participants_title") rightPanel.headerSubtitleText = qsTr("group_call_participant_selected", '', addParticipantLayout.selectedParticipants.length).arg(addParticipantLayout.selectedParticipants.length) } else { rightPanel.headerSubtitleText = "" } } } } } } } } Component { id: encryptionPanel EncryptionSettings { objectName: "encryptionPanel" call: mainWindow.call width: parent.width onEncryptionValidationRequested: zrtpValidation.open() } } Component { id: statsPanel CallStatistics { objectName: "statsPanel" width: parent.width call: mainWindow.call } } Component { id: waitingRoom WaitingRoom { id: waitingRoomIn objectName: "waitingRoom" Layout.alignment: Qt.AlignCenter onSettingsButtonCheckedChanged: { if (settingsButtonChecked) { rightPanel.visible = true rightPanel.replace(settingsPanel) } else { rightPanel.visible = false } } Binding { target: callStatusIcon when: middleItemStackView.currentItem.objectName === "waitingRoom" property: "imageSource" value: AppIcons.usersThree } Binding { target: callStatusText when: middleItemStackView.currentItem.objectName === "waitingRoom" property: "text" value: waitingRoomIn.conferenceInfo ? waitingRoomIn.conferenceInfo.core.subject : '' } Binding { target: conferenceDate when: middleItemStackView.currentItem.objectName === "waitingRoom" property: "text" value: waitingRoomIn.conferenceInfo ? waitingRoomIn.conferenceInfo.core.startEndDateString : '' } Connections { target: rightPanel function onVisibleChanged() { if (!rightPanel.visible) { waitingRoomIn.settingsButtonChecked = false } } } Connections { target: mainWindow function onSetUpConferenceRequested(conferenceInfo) { waitingRoomIn.conferenceInfo = conferenceInfo } } onJoinConfRequested: uri => { mainWindow.joinConference(uri, { "microEnabled": microEnabled, "localVideoEnabled": localVideoEnabled }) } onCancelJoiningRequested: mainWindow.cancelJoinConference() onCancelAfterJoinRequested: mainWindow.cancelAfterJoin() } } Component { id: inCallItem Loader { property string objectName: "inCallItem" asynchronous: true sourceComponent: Item { CallLayout { anchors.fill: parent anchors.leftMargin: Math.round(20 * DefaultStyle.dp) anchors.rightMargin: rightPanel.visible ? 0 : Math.round(10 * DefaultStyle.dp) // Grid and AS have 10 in right margin (so apply -10 here) anchors.topMargin: Math.round(10 * DefaultStyle.dp) call: mainWindow.call callTerminatedByUser: mainWindow.callTerminatedByUser } } } } RowLayout { id: bottomButtonsLayout Layout.alignment: Qt.AlignHCenter spacing: Math.round(58 * DefaultStyle.dp) visible: middleItemStackView.currentItem.objectName == "inCallItem" function refreshLayout() { if (mainWindow.callState === LinphoneEnums.CallState.Connected || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning || mainWindow.callState === LinphoneEnums.CallState.Paused || mainWindow.callState === LinphoneEnums.CallState.PausedByRemote) { connectedCallButtons.visible = bottomButtonsLayout.visible moreOptionsButton.visible = bottomButtonsLayout.visible bottomButtonsLayout.layoutDirection = Qt.RightToLeft } else if (mainWindow.callState === LinphoneEnums.CallState.OutgoingInit) { connectedCallButtons.visible = false bottomButtonsLayout.layoutDirection = Qt.LeftToRight moreOptionsButton.visible = false } } Connections { target: mainWindow function onCallStateChanged() { bottomButtonsLayout.refreshLayout() } function onCallChanged() { bottomButtonsLayout.refreshLayout() } } function setButtonsEnabled(enabled) { for (var i = 0; i < children.length; ++i) { children[i].enabled = false } } BigButton { Layout.row: 0 icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) //: "Terminer l'appel" ToolTip.text: qsTr("call_action_end_call") Layout.preferredWidth: Math.round(75 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) radius: Math.round(71 * DefaultStyle.dp) style: ButtonStyle.phoneRed Layout.column: mainWindow.callState == LinphoneEnums.CallState.OutgoingInit || mainWindow.callState == LinphoneEnums.CallState.OutgoingProgress || mainWindow.callState == LinphoneEnums.CallState.OutgoingRinging || mainWindow.callState == LinphoneEnums.CallState.OutgoingEarlyMedia || mainWindow.callState == LinphoneEnums.CallState.IncomingReceived ? 0 : bottomButtonsLayout.columns - 1 onClicked: { mainWindow.callTerminatedByUser = true mainWindow.endCall(mainWindow.call) } } RowLayout { id: connectedCallButtons visible: false Layout.row: 0 Layout.column: 1 spacing: Math.round(10 * DefaultStyle.dp) CheckableButton { id: pauseButton Layout.preferredWidth: Math.round(55 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) //: "Reprendre l'appel" ToolTip.text: checked ? qsTr("call_action_resume_call") //: "Mettre l'appel en pause" : qsTr("call_action_pause_call") background: Rectangle { anchors.fill: parent radius: Math.round(71 * DefaultStyle.dp) color: parent.enabled ? parent.checked ? DefaultStyle.success_500main : parent.pressed ? DefaultStyle.main2_400 : DefaultStyle.grey_500 : DefaultStyle.grey_600 } enabled: mainWindow.conference || mainWindow.callState != LinphoneEnums.CallState.PausedByRemote icon.source: enabled && checked ? AppIcons.play : AppIcons.phonePause checked: mainWindow.call && mainWindow.callState == LinphoneEnums.CallState.Paused || mainWindow.callState == LinphoneEnums.CallState.Pausing || (!mainWindow.conference && mainWindow.callState == LinphoneEnums.CallState.PausedByRemote) onClicked: { mainWindow.call.core.lSetPaused( !mainWindow.call.core.paused) } } CheckableButton { id: transferCallButton visible: !mainWindow.conference icon.source: AppIcons.transferCall Layout.preferredWidth: Math.round(55 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) contentImageColor: DefaultStyle.grey_0 //: "Transférer l'appel" ToolTip.text: qsTr("call_action_transfer_call") onToggled: { console.log("checked transfer changed", checked) if (checked) { rightPanel.visible = true rightPanel.replace(callTransferPanel) } else { rightPanel.visible = false } } } CheckableButton { id: newCallButton checkable: true icon.source: AppIcons.newCall Layout.preferredWidth: Math.round(55 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) //: "Initier un nouvel appel" ToolTip.text: qsTr("call_action_start_new_call_hint") onToggled: { console.log("checked newcall changed", checked) if (checked) { rightPanel.visible = true rightPanel.replace(newCallPanel) } else { rightPanel.visible = false } } } CheckableButton { id: callListButton Layout.preferredWidth: Math.round(55 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) checkable: true icon.source: AppIcons.callList icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) //: "Afficher la liste d'appels" ToolTip.text: qsTr("call_display_call_list_hint") onToggled: { if (checked) { rightPanel.visible = true rightPanel.replace(callListPanel) } else { rightPanel.visible = false } } } } RowLayout { Layout.row: 0 Layout.column: mainWindow.callState == LinphoneEnums.CallState.OutgoingInit || mainWindow.callState == LinphoneEnums.CallState.OutgoingProgress || mainWindow.callState == LinphoneEnums.CallState.OutgoingRinging || mainWindow.callState == LinphoneEnums.CallState.OutgoingEarlyMedia || mainWindow.callState == LinphoneEnums.CallState.IncomingReceived ? bottomButtonsLayout.columns - 1 : 0 spacing: Math.round(10 * DefaultStyle.dp) CheckableButton { id: videoCameraButton visible: SettingsCpp.videoEnabled enabled: mainWindow.conferenceInfo || (mainWindow.callState === LinphoneEnums.CallState.Connected || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning) iconUrl: AppIcons.videoCamera checkedIconUrl: AppIcons.videoCameraSlash //: "Désactiver la vidéo" //: "Activer la vidéo" ToolTip.text: mainWindow.localVideoEnabled ? qsTr("call_deactivate_video_hint") : qsTr("call_activate_video_hint") checked: !mainWindow.localVideoEnabled Layout.preferredWidth: Math.round(55 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) onClicked: mainWindow.call.core.lSetLocalVideoEnabled( !mainWindow.call.core.localVideoEnabled) } CheckableButton { iconUrl: AppIcons.microphone ToolTip.text: mainWindow.call && mainWindow.call.core.microphoneMuted //: "Activer le micro" ? qsTr("call_activate_microphone") //: "Désactiver le micro" : qsTr("call_deactivate_microphone") checkedIconUrl: AppIcons.microphoneSlash checked: mainWindow.call && mainWindow.call.core.microphoneMuted Layout.preferredWidth: Math.round(55 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) onClicked: mainWindow.call.core.lSetMicrophoneMuted( !mainWindow.call.core.microphoneMuted) } CheckableButton { id: screencastPanelButton iconUrl: AppIcons.screencast visible: !!mainWindow.conference //: Partager l'écran… ToolTip.text: qsTr("call_share_screen_hint") Layout.preferredWidth: Math.round(55 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) onToggled: { if (checked) { rightPanel.visible = true rightPanel.replace(screencastPanel) } else { rightPanel.visible = false } } } CheckableButton { id: chatPanelButton iconUrl: AppIcons.chatTeardropText //: Open chat… ToolTip.text: qsTr("call_open_chat_hint") Layout.preferredWidth: Math.round(55 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) onToggled: { if (checked) { rightPanel.visible = true rightPanel.replace(chatPanel) } else { rightPanel.visible = false } } } CheckableButton { visible: false checkable: false iconUrl: AppIcons.handWaving //: "Lever la main" ToolTip.text: qsTr("call_rise_hand_hint") Layout.preferredWidth: Math.round(55 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) } CheckableButton { visible: false iconUrl: AppIcons.smiley //: "Envoyer une réaction" ToolTip.text: qsTr("call_send_reaction_hint") Layout.preferredWidth: Math.round(55 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) } CheckableButton { id: participantListButton //: "Gérer les participants" ToolTip.text: qsTr("call_manage_participants_hint") visible: mainWindow.conference iconUrl: AppIcons.usersTwo Layout.preferredWidth: Math.round(55 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) onToggled: { if (checked) { rightPanel.visible = true rightPanel.replace(participantListPanel) } else { rightPanel.visible = false } } } PopupButton { id: moreOptionsButton //: "Plus d'options…" ToolTip.text: qsTr("call_more_options_hint") Layout.preferredWidth: Math.round(55 * DefaultStyle.dp) Layout.preferredHeight: Math.round(55 * DefaultStyle.dp) popup.topPadding: Math.round(20 * DefaultStyle.dp) popup.bottomPadding: Math.round(20 * DefaultStyle.dp) popup.leftPadding: Math.round(10 * DefaultStyle.dp) popup.rightPadding: Math.round(10 * DefaultStyle.dp) style: ButtonStyle.checkable icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) Connections { target: moreOptionsButton.popup function onOpened() { moreOptionsButton.popup.y = -moreOptionsButton.popup.height - moreOptionsButton.popup.padding } } popup.contentItem: ColumnLayout { id: optionsList spacing: Math.round(5 * DefaultStyle.dp) IconLabelButton { Layout.fillWidth: true visible: mainWindow.conference icon.source: AppIcons.squaresFour icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) //: "Modifier la disposition" text: qsTr("call_action_change_conference_layout") style: ButtonStyle.noBackground onClicked: { rightPanel.visible = true rightPanel.replace(changeLayoutPanel) moreOptionsButton.close() } } IconLabelButton { Layout.fillWidth: true icon.source: AppIcons.fullscreen //: "Mode Plein écran" text: qsTr("call_action_full_screen") icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) checkable: true style: ButtonStyle.noBackground Binding on checked { value: mainWindow.visibility === Window.FullScreen } onToggled: { if (checked) { mainWindow.showFullScreen() } else { mainWindow.showNormal() } moreOptionsButton.close() } } IconLabelButton { Layout.fillWidth: true icon.source: AppIcons.dialer text: qsTr("call_action_show_dialer") icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) style: ButtonStyle.noBackground onClicked: { rightPanel.visible = true rightPanel.replace(dialerPanel) moreOptionsButton.close() } } IconLabelButton { Layout.fillWidth: true checkable: true style: ButtonStyle.noBackground icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) visible: mainWindow.call && !mainWindow.conference && !SettingsCpp.disableCallRecordings enabled: mainWindow.call && mainWindow.call.core.recordable icon.source: AppIcons.recordFill checked: mainWindow.call && mainWindow.call.core.recording hoveredImageColor: contentImageColor contentImageColor: mainWindow.call && mainWindow.call.core.recording ? DefaultStyle.danger_500main : DefaultStyle.main2_500main text: mainWindow.call && mainWindow.call.core.recording //: "Terminer l'enregistrement" ? qsTr("call_action_stop_recording") //: "Enregistrer l'appel" : qsTr("call_action_record") textColor: mainWindow.call && mainWindow.call.core.recording ? DefaultStyle.danger_500main : DefaultStyle.main2_500main hoveredTextColor: textColor onToggled: { if (mainWindow.call) if (mainWindow.call.core.recording) mainWindow.call.core.lStopRecording( ) else mainWindow.call.core.lStartRecording() } } IconLabelButton { Layout.fillWidth: true checkable: true style: ButtonStyle.noBackground icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) icon.source: !mainWindow.call || mainWindow.call.core.speakerMuted ? AppIcons.speakerSlash : AppIcons.speaker contentImageColor: mainWindow.call && mainWindow.call.core.speakerMuted ? DefaultStyle.danger_500main : DefaultStyle.main2_500main hoveredImageColor: contentImageColor text: mainWindow.call && mainWindow.call.core.speakerMuted //: "Activer le son" ? qsTr("call_activate_speaker_hint") //: "Désactiver le son" : qsTr("call_deactivate_speaker_hint") textColor: mainWindow.call && mainWindow.call.core.speakerMuted ? DefaultStyle.danger_500main : DefaultStyle.main2_500main hoveredTextColor: textColor onCheckedChanged: { if (mainWindow.call) mainWindow.call.core.lSetSpeakerMuted( !mainWindow.call.core.speakerMuted) } } IconLabelButton { Layout.fillWidth: true icon.source: AppIcons.settings icon.width: Math.round(32 * DefaultStyle.dp) icon.height: Math.round(32 * DefaultStyle.dp) //: "Paramètres" text: qsTr("call_action_go_to_settings") style: ButtonStyle.noBackground onClicked: { rightPanel.visible = true rightPanel.replace(settingsPanel) moreOptionsButton.close() } } } } } } } } }