mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-04-19 16:38:28 +00:00
- List conferences - Call conference (only from conference list) - Prepare Mozaic layout (not yet link to conference)
530 lines
No EOL
16 KiB
QML
530 lines
No EOL
16 KiB
QML
import QtQuick 2.7
|
|
import QtQuick.Layouts 1.3
|
|
import QtQuick.Controls 2.3
|
|
|
|
import Common 1.0
|
|
import Linphone 1.0
|
|
//import LinphoneUtils 1.0
|
|
import LinphoneEnums 1.0
|
|
|
|
import App.Styles 1.0
|
|
import Common.Styles 1.0
|
|
import Units 1.0
|
|
import UtilsCpp 1.0
|
|
import ColorsList 1.0
|
|
|
|
// =============================================================================
|
|
|
|
DialogPlus {
|
|
id: conferenceManager
|
|
property ConferenceInfoModel conferenceInfoModel: ConferenceInfoModel{}
|
|
|
|
readonly property int minParticipants: 1
|
|
|
|
buttons: [
|
|
ColumnLayout{
|
|
Layout.fillWidth: true
|
|
Layout.topMargin:15
|
|
Layout.alignment: Qt.AlignLeft
|
|
Layout.leftMargin: 15
|
|
spacing:4
|
|
Text {
|
|
Layout.fillWidth: true
|
|
//: 'Would you like to encrypt your conference?' : Ask about setting the conference as secured.
|
|
text:qsTr('askEncryption')
|
|
color: NewConferenceStyle.askEncryptionColor
|
|
font.pointSize: Units.dp * 11
|
|
font.weight: Font.DemiBold
|
|
}
|
|
Item{
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 50
|
|
Icon{
|
|
id:secureOff
|
|
anchors.left:parent.left
|
|
anchors.leftMargin : 0
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width:20
|
|
height:20
|
|
icon: 'secure_off'
|
|
iconSize:20
|
|
}
|
|
Switch{
|
|
id:secureSwitch
|
|
anchors.left:secureOff.right
|
|
anchors.leftMargin : 5
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width:50
|
|
enabled:true
|
|
checked: !SettingsModel.standardChatEnabled && SettingsModel.secureChatEnabled
|
|
|
|
onClicked: {
|
|
var newCheck = checked
|
|
if(SettingsModel.standardChatEnabled && checked || SettingsModel.secureChatEnabled && !checked)
|
|
newCheck = !checked;
|
|
|
|
checked = newCheck;
|
|
}
|
|
indicatorStyle: SwitchStyle.aux
|
|
}
|
|
Icon{
|
|
id:secureOn
|
|
anchors.left:secureSwitch.right
|
|
anchors.leftMargin : 15
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width:20
|
|
height:20
|
|
icon: 'secure_on'
|
|
iconSize:20
|
|
}
|
|
}
|
|
},
|
|
TextButtonA {
|
|
//: 'Cancel' : Cancel button
|
|
text: qsTr('cancelButton')
|
|
capitalization: Font.AllUppercase
|
|
|
|
onClicked: exit(0)
|
|
},
|
|
TextButtonB {
|
|
enabled: selectedParticipants.count >= conferenceManager.minParticipants && subject.text != '' && AccountSettingsModel.conferenceURI != ''
|
|
//: 'Launch' : Start button
|
|
text: qsTr('startButton')
|
|
capitalization: Font.AllUppercase
|
|
|
|
function getInviteMode(){
|
|
//return inviteAppAccountCheckBox.checked ? LinphoneEnums::
|
|
return 0;
|
|
}
|
|
|
|
onClicked: {
|
|
if( scheduledSwitch.checked){
|
|
var startDateTime = new Date()
|
|
startDateTime.setDate(Date.fromLocaleDateString(locale, dateField.text, Locale.ShortFormat))
|
|
startDateTime.setTime( Date.fromLocaleTimeString(locale, timeField.text, Locale.ShortFormat))
|
|
conferenceInfoModel.dateTime = startDateTime
|
|
}
|
|
conferenceInfoModel.subject = subject.text
|
|
conferenceInfoModel.description = description.text
|
|
|
|
conferenceInfoModel.setParticipants(selectedParticipants.participantListModel)
|
|
var callsWindow = App.getCallsWindow()
|
|
App.smartShowWindow(callsWindow)
|
|
callsWindow.openConference()
|
|
CallsListModel.createConference(conferenceInfoModel, secureSwitch.checked, getInviteMode(), false )
|
|
exit(1)
|
|
}
|
|
TooltipArea{
|
|
visible: AccountSettingsModel.conferenceURI == '' || subject.text == '' || selectedParticipants.count < conferenceManager.minParticipants
|
|
maxWidth: participantView.width
|
|
delay:0
|
|
text: {
|
|
var txt = '\n';
|
|
if( subject.text == '')
|
|
//: 'You need to fill a subject.' : Tooltip to warn a user on missing field.
|
|
txt ='- ' + qsTr('missingSubject') + '\n'
|
|
if( selectedParticipants.count < conferenceManager.minParticipants)
|
|
//: 'You need at least %1 participant.' : Tooltip to warn a user that there are not enough participants for the chat creation.
|
|
txt += '- ' + qsTr('missingParticipants', '', conferenceManager.minParticipants).arg(conferenceManager.minParticipants) + '\n'
|
|
if( AccountSettingsModel.conferenceURI == '')
|
|
//: 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missong in its configuration.
|
|
txt += '- ' + qsTr('missingConferenceURI') + '\n'
|
|
return txt;
|
|
}
|
|
}
|
|
}
|
|
|
|
]
|
|
|
|
buttonsAlignment: Qt.AlignRight
|
|
buttonsLeftMargin: 15
|
|
//: 'Start a video conference' : Title of a popup about creation of a video conference
|
|
title:qsTr('newConferenceTitle')
|
|
|
|
height: window.height - 100
|
|
width: window.width - 100
|
|
expandHeight: true
|
|
|
|
// ---------------------------------------------------------------------------
|
|
RowLayout {
|
|
height: parent.height
|
|
width: parent.width
|
|
spacing: 0
|
|
ColumnLayout {
|
|
Layout.fillHeight: true
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: 10
|
|
spacing: 10
|
|
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
Layout.rightMargin: 15
|
|
spacing:5
|
|
|
|
Text{
|
|
textFormat: Text.RichText
|
|
//: 'Subject' : Label of a text field about the subject of the chat room
|
|
text :qsTr('subjectLabel') +'<span style="color:red">*</span>'
|
|
color: NewConferenceStyle.subjectTitleColor
|
|
font.pointSize: Units.dp * 11
|
|
font.weight: Font.DemiBold
|
|
}
|
|
TextField {
|
|
id:subject
|
|
Layout.fillWidth: true
|
|
//: 'Give a subject' : Placeholder in a form about setting a subject
|
|
placeholderText : qsTr('subjectPlaceholder')
|
|
text: conferenceInfoModel && conferenceInfoModel.subject || ''
|
|
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
|
|
TooltipArea{
|
|
//: 'Current subject of the Chat Room. It cannot be empty'
|
|
//~ Tooltip Explanation about the subject of the chat room
|
|
text : qsTr('subjectTooltip')
|
|
}
|
|
}
|
|
}
|
|
Rectangle{
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: scheduledSwitch.checked ? 120 : 50
|
|
Layout.rightMargin: 15
|
|
color: '#F7F7F7'
|
|
ColumnLayout{
|
|
anchors.fill: parent
|
|
spacing: 0
|
|
RowLayout{
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 50
|
|
Switch{
|
|
id:scheduledSwitch
|
|
Layout.leftMargin : 5
|
|
Layout.alignment: Qt.AlignVCenter
|
|
width:50
|
|
enabled: true
|
|
checked: true
|
|
|
|
onClicked: {
|
|
//checked = !checked
|
|
}
|
|
indicatorStyle: SwitchStyle.aux
|
|
}
|
|
Text {
|
|
Layout.fillWidth: true
|
|
Layout.rightMargin: 15
|
|
//: 'Would you like to schedule your conference?' : Ask about setting the conference as scheduled.
|
|
text: 'Souhaitez-vous programmer cette conférence pour plus tard ?'
|
|
color: NewConferenceStyle.askEncryptionColor
|
|
font.pointSize: Units.dp * 10
|
|
font.weight: Font.DemiBold
|
|
wrapMode: Text.WordWrap
|
|
}
|
|
}
|
|
GridLayout{
|
|
id: scheduleForm
|
|
visible: scheduledSwitch.checked
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
columns: 4
|
|
property var locale: Qt.locale()
|
|
property date currentDate: new Date()
|
|
property int cellWidth: (parent.width-15)/columns
|
|
Component.onCompleted: scheduleForm.updateDateTime()
|
|
|
|
|
|
|
|
Text{text: 'Date*'; Layout.preferredWidth: parent.cellWidth}
|
|
Text{text: 'Heure de début*'; Layout.preferredWidth: parent.cellWidth}
|
|
Text{text: 'Durée'; Layout.preferredWidth: parent.cellWidth}
|
|
Text{text: 'Fuseau horaire'; Layout.preferredWidth: parent.cellWidth}
|
|
TextField{id: dateField; Layout.preferredWidth: parent.cellWidth
|
|
function getDate(){
|
|
return Date.fromLocaleDateString(scheduleForm.locale, text,'yyyy/MM/dd')
|
|
}
|
|
function setDate(date){
|
|
text = date.toLocaleDateString(scheduleForm.locale, 'yyyy/MM/dd')
|
|
}
|
|
MouseArea{
|
|
anchors.fill: parent
|
|
onClicked: {
|
|
if( rightStackView.currentItemType === 1) {
|
|
rightStackView.currentItemType = 0
|
|
rightStackView.pop()// Cancel
|
|
}else {
|
|
if( rightStackView.depth > 1 )
|
|
rightStackView.pop()//Remove previous request
|
|
rightStackView.currentItemType = 1
|
|
rightStackView.push(datePicker, {selectedDate: new Date(dateField.getDate())})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
TextField{id: timeField; Layout.preferredWidth: parent.cellWidth
|
|
function getTime(){
|
|
return Date.fromLocaleTimeString(scheduleForm.locale, timeField.text, 'hh:mm')
|
|
}
|
|
function setTime(date){
|
|
text = date.toLocaleTimeString(scheduleForm.locale, 'hh:mm')
|
|
}
|
|
MouseArea{
|
|
anchors.fill: parent
|
|
onClicked: {
|
|
if( rightStackView.currentItemType === 2) {
|
|
rightStackView.currentItemType = 0
|
|
rightStackView.pop()// Cancel
|
|
}else {
|
|
if( rightStackView.depth > 1 )
|
|
rightStackView.pop()//Remove previous request
|
|
rightStackView.currentItemType = 2
|
|
rightStackView.push(timePicker,{selectedTime: new Date(timeField.getTime())})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
NumericField{ text: '1200'; readOnly: true; Layout.preferredWidth: parent.cellWidth}
|
|
TextField{ text: 'Paris'; readOnly: true; Layout.preferredWidth: parent.cellWidth}
|
|
function updateDateTime(){
|
|
var storedDate = new Date()
|
|
if( dateField.text != '' && timeField.text != ''){
|
|
storedDate.setDate(dateField.getDate())
|
|
storedDate.setTime(timeField.getTime() )
|
|
}
|
|
var currentDate = new Date()
|
|
if(currentDate >= storedDate){
|
|
var nextStoredDate = UtilsCpp.addMinutes(new Date(), 5)
|
|
dateField.setDate(nextStoredDate)
|
|
timeField.setTime(nextStoredDate)
|
|
}
|
|
}
|
|
Timer{
|
|
running: scheduleForm.visible
|
|
repeat: true
|
|
interval: 1000
|
|
onTriggered: {
|
|
scheduleForm.updateDateTime()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ColumnLayout {
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
Layout.rightMargin: 15
|
|
spacing:5
|
|
Text{
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 20
|
|
textFormat: Text.RichText
|
|
//: 'Add a description' : Label of a text field about the description of the conference
|
|
text : 'Ajouter une description'
|
|
color: NewConferenceStyle.subjectTitleColor
|
|
font.pointSize: Units.dp * 10
|
|
font.weight: Font.DemiBold
|
|
}
|
|
TextAreaField {
|
|
id: description
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
//: 'Description' : Placeholder in a form about setting a description
|
|
//placeholderText : 'Description'
|
|
text: ''
|
|
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
|
|
TooltipArea{
|
|
//: 'This description will describe the conference' : Explanation about the description of the conference
|
|
text : 'This description will describe the conference'
|
|
}
|
|
}
|
|
}
|
|
ColumnLayout{
|
|
Layout.fillWidth: true
|
|
//Layout.preferredHeight: 60
|
|
spacing: 5
|
|
CheckBoxText {
|
|
id: inviteAppAccountCheckBox
|
|
|
|
text: 'Envoyer l\'invitation via mon compte Linphone'
|
|
width: parent.width
|
|
checked: true
|
|
|
|
onClicked: {
|
|
console.log('Send invite with Linphone account: ' + checked)
|
|
}
|
|
}
|
|
CheckBoxText {
|
|
id: inviteEmailCheckBox
|
|
|
|
text: 'Envoyer l\'invitation via mon adresse mail'
|
|
width: parent.width
|
|
|
|
onClicked: {
|
|
console.log('Send invite with email: ' + checked)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
StackView{
|
|
id: rightStackView
|
|
|
|
property int currentItemType: 0
|
|
|
|
Layout.fillHeight: true
|
|
Layout.fillWidth: true
|
|
Layout.minimumWidth: 200
|
|
Layout.topMargin: 10
|
|
Layout.bottomMargin: 10
|
|
|
|
clip: true
|
|
// -------------------------------------------------------------------------
|
|
// See and remove selected addresses.
|
|
// -------------------------------------------------------------------------
|
|
initialItem: ColumnLayout{
|
|
//anchors.fill: parent
|
|
|
|
Rectangle{
|
|
Layout.fillHeight: true
|
|
Layout.fillWidth: true
|
|
border.width: 1
|
|
border.color: NewConferenceStyle.addressesBorderColor
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
anchors.topMargin: 15
|
|
anchors.leftMargin: 10
|
|
anchors.rightMargin: 10
|
|
spacing: 0
|
|
|
|
SmartSearchBar {
|
|
id: smartSearchBar
|
|
|
|
Layout.fillWidth: true
|
|
Layout.topMargin: ConferenceManagerStyle.columns.selector.spacing
|
|
|
|
showHeader:false
|
|
|
|
maxMenuHeight: MainWindowStyle.searchBox.maxHeight
|
|
//: 'Select participants' : Placeholder for a search on participant to add them in selection.
|
|
placeholderText: qsTr('participantSelectionPlaceholder')
|
|
//: 'Search in your contacts or add a custom one to the chat room.'
|
|
tooltipText: qsTr('participantSelectionTooltip')
|
|
|
|
actions:[{
|
|
colorSet: NewConferenceStyle.addParticipant,
|
|
secure: secureSwitch.checked,
|
|
visible: true,
|
|
secureIconVisibleHandler : function(entry) {
|
|
return UtilsCpp.hasCapability(entry.sipAddress, LinphoneEnums.FriendCapabilityLimeX3Dh)
|
|
},
|
|
handler: function (entry) {
|
|
selectedParticipants.addAddress(entry.sipAddress)
|
|
smartSearchBar.addAddressToIgnore(entry.sipAddress);
|
|
},
|
|
}]
|
|
|
|
onEntryClicked: {
|
|
selectedParticipants.addAddress(entry.sipAddress)
|
|
smartSearchBar.addAddressToIgnore(entry.sipAddress);
|
|
}
|
|
}
|
|
Text{
|
|
Layout.preferredHeight: 20
|
|
Layout.rightMargin: 65
|
|
Layout.alignment: Qt.AlignRight | Qt.AlignBottom
|
|
Layout.topMargin: ConferenceManagerStyle.columns.selector.spacing
|
|
//: 'Admin' : Admin(istrator)
|
|
//~ one word for admin status
|
|
text : qsTr('adminStatus')
|
|
|
|
color: NewConferenceStyle.addressesAdminColor
|
|
font.pointSize: Units.dp * 11
|
|
font.weight: Font.Light
|
|
visible: participantView.count > 0
|
|
|
|
}
|
|
ScrollableListViewField {
|
|
Layout.fillHeight: true
|
|
Layout.fillWidth: true
|
|
Layout.bottomMargin: 5
|
|
|
|
textFieldStyle: TextFieldStyle.unbordered
|
|
|
|
ParticipantsView {
|
|
id: participantView
|
|
anchors.fill: parent
|
|
|
|
showContactAddress:false
|
|
showSwitch : true
|
|
showSeparator: false
|
|
isSelectable: false
|
|
showInvitingIndicator: false
|
|
function removeParticipant(entry){
|
|
smartSearchBar.removeAddressToIgnore(entry.sipAddress)
|
|
selectedParticipants.removeModel(entry)
|
|
++lastContacts.reloadCount
|
|
}
|
|
|
|
|
|
actions: [{
|
|
colorSet: NewConferenceStyle.removeParticipant,
|
|
secure:0,
|
|
visible:true,
|
|
//: 'Remove this participant from the selection' : Explanation about removing participant from a selection
|
|
//~ Tooltip This is a tooltip
|
|
tooltipText: qsTr('removeParticipantSelection'),
|
|
handler: function (entry) {
|
|
removeParticipant(entry)
|
|
}
|
|
}]
|
|
|
|
genSipAddress: ''
|
|
|
|
model: ParticipantProxyModel {
|
|
id:selectedParticipants
|
|
chatRoomModel:null
|
|
|
|
}
|
|
onEntryClicked: actions[0].handler(entry)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Item{
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 20
|
|
Text{
|
|
anchors.fill:parent
|
|
textFormat: Text.RichText
|
|
//: 'Required' : Word relative to a star to explain that it is a requirement (Field form)
|
|
text : '<span style="color:red">*</span> '+qsTr('requiredField')
|
|
//font.weight: Font.DemiBold
|
|
color: NewConferenceStyle.requiredColor
|
|
font.pointSize: Units.dp * 8
|
|
}
|
|
}
|
|
}
|
|
//----------------------------------------------------
|
|
// STACKVIEWS
|
|
//----------------------------------------------------
|
|
Component{
|
|
id: datePicker
|
|
DatePicker{
|
|
onClicked: {
|
|
dateField.setDate(date)
|
|
rightStackView.currentItemType = 0
|
|
rightStackView.pop()
|
|
}
|
|
}
|
|
}
|
|
|
|
Component{
|
|
id: timePicker
|
|
TimePicker{
|
|
onClicked: {
|
|
timeField.setTime(date)
|
|
rightStackView.currentItemType = 0
|
|
rightStackView.pop()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |