diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp index a71988c6f..b49c6726b 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp @@ -84,9 +84,9 @@ ConferenceInfoModel::ConferenceInfoModel (QObject * parent) : QObject(parent){ mConferenceInfo = linphone::Factory::get()->createConferenceInfo(); QDateTime currentDateTime = QDateTime::currentDateTime(); QDateTime utc = currentDateTime.addSecs( -mTimeZone.offsetFromUtc(currentDateTime)); - mConferenceInfo->setDateTime(utc.toMSecsSinceEpoch() / 1000); - mConferenceInfo->setDuration(1200); - mIsScheduled = true; + mConferenceInfo->setDateTime(0); + mConferenceInfo->setDuration(0); + mIsScheduled = false; auto accountAddress = CoreManager::getInstance()->getCore()->getDefaultAccount()->getContactAddress(); accountAddress->clean(); mConferenceInfo->setOrganizer(accountAddress); @@ -97,7 +97,7 @@ ConferenceInfoModel::ConferenceInfoModel (std::shared_ptrgetEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE mTimeZone = QTimeZone::systemTimeZone(); mConferenceInfo = conferenceInfo; - mIsScheduled = true; + mIsScheduled = (mConferenceInfo->getDateTime() != 0 || mConferenceInfo->getDuration() != 0); } ConferenceInfoModel::~ConferenceInfoModel () { @@ -253,6 +253,7 @@ void ConferenceInfoModel::createConference(const int& securityLevel, const int& mConferenceScheduler = ConferenceScheduler::create(); + mConferenceScheduler->mSendInvite = inviteMode; connect(mConferenceScheduler.get(), &ConferenceScheduler::invitationsSent, this, &ConferenceInfoModel::onInvitationsSent); connect(mConferenceScheduler.get(), &ConferenceScheduler::stateChanged, this, &ConferenceInfoModel::onStateChanged); mConferenceScheduler->getConferenceScheduler()->setInfo(mConferenceInfo); diff --git a/linphone-app/src/components/conferenceScheduler/ConferenceScheduler.cpp b/linphone-app/src/components/conferenceScheduler/ConferenceScheduler.cpp index 1f74d6315..2003c2c5f 100644 --- a/linphone-app/src/components/conferenceScheduler/ConferenceScheduler.cpp +++ b/linphone-app/src/components/conferenceScheduler/ConferenceScheduler.cpp @@ -57,9 +57,11 @@ void ConferenceScheduler::onStateChanged(linphone::ConferenceSchedulerState stat qDebug() << "ConferenceScheduler::onStateChanged : " << (int)state; emit stateChanged(state); if( state == linphone::ConferenceSchedulerState::Ready) { - std::shared_ptr params = CoreManager::getInstance()->getCore()->createDefaultChatRoomParams(); - params->setBackend(linphone::ChatRoomBackend::Basic); - mConferenceScheduler->sendInvitations(params); + if( (mSendInvite & 1) == 1){ + std::shared_ptr params = CoreManager::getInstance()->getCore()->createDefaultChatRoomParams(); + params->setBackend(linphone::ChatRoomBackend::Basic); + mConferenceScheduler->sendInvitations(params); + } } } diff --git a/linphone-app/src/components/conferenceScheduler/ConferenceScheduler.hpp b/linphone-app/src/components/conferenceScheduler/ConferenceScheduler.hpp index ecc2e5407..52155ad75 100644 --- a/linphone-app/src/components/conferenceScheduler/ConferenceScheduler.hpp +++ b/linphone-app/src/components/conferenceScheduler/ConferenceScheduler.hpp @@ -39,6 +39,8 @@ public: virtual void onStateChanged(linphone::ConferenceSchedulerState state); virtual void onInvitationsSent(const std::list> & failedInvitations); + int mSendInvite = 1;// TODO : Enum for app = 1, email=2. Both = 3 + signals: void stateChanged(linphone::ConferenceSchedulerState state); void invitationsSent(const std::list> & failedInvitations); diff --git a/linphone-app/ui/modules/Common/Form/Fields/TextAreaField.qml b/linphone-app/ui/modules/Common/Form/Fields/TextAreaField.qml index f872e70ba..a4a6c6722 100644 --- a/linphone-app/ui/modules/Common/Form/Fields/TextAreaField.qml +++ b/linphone-app/ui/modules/Common/Form/Fields/TextAreaField.qml @@ -39,6 +39,7 @@ Rectangle { ScrollBar.vertical: ForceScrollBar { id: scrollBar + policy: flickable.contentHeight > flickable.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff } TextArea.flickable: TextArea { diff --git a/linphone-app/ui/modules/Common/Picker/TimePicker.qml b/linphone-app/ui/modules/Common/Picker/TimePicker.qml index c187458ae..0d5936f9f 100644 --- a/linphone-app/ui/modules/Common/Picker/TimePicker.qml +++ b/linphone-app/ui/modules/Common/Picker/TimePicker.qml @@ -14,9 +14,19 @@ Item{ property int centerPosition: Math.min(height, width)/2 property int middleMinSize: centerPosition - border // Minus border - + signal newDate(date date) signal clicked(date date) - + + function getDate(){ + var d = new Date() + if(outer.currentItem) + d.setHours(outer.currentItem.text) + if(inner.currentItem) + d.setMinutes(inner.currentItem.text) + d.setSeconds(0) + return d; + } + PathView { id: outer model: 24 @@ -134,6 +144,7 @@ Item{ font.pointSize: Units.dp * 12 font.bold: true text: outer.currentItem.text.length < 2 ? '0' + outer.currentItem.text : outer.currentItem.text + onTextChanged: mainItem.newDate(mainItem.getDate()) } Text { id: div @@ -146,17 +157,15 @@ Item{ font.pointSize: Units.dp * 12 font.bold: true text: inner.currentItem.text.length < 2 ? '0' + inner.currentItem.text : inner.currentItem.text + onTextChanged: mainItem.newDate(mainItem.getDate()) } } MouseArea { anchors.fill: selectedTimeArea - onClicked: { - var d = new Date() - d.setHours(outer.currentItem.text) - d.setMinutes(inner.currentItem.text) - mainItem.clicked(d) + onClicked: { + mainItem.clicked(mainItem.getDate()) } } Component.onCompleted: { diff --git a/linphone-app/ui/views/App/Dialog/NewConference.qml b/linphone-app/ui/views/App/Dialog/NewConference.qml index 93de5f526..2e6f6980b 100644 --- a/linphone-app/ui/views/App/Dialog/NewConference.qml +++ b/linphone-app/ui/views/App/Dialog/NewConference.qml @@ -109,19 +109,25 @@ DialogPlus { capitalization: Font.AllUppercase function getInviteMode(){ - return 0; + return scheduledSwitch.checked ? (inviteAppAccountCheckBox.checked ? 1 : 0) + (inviteEmailCheckBox.checked ? 2 : 0) + : 0 } onClicked: { + if( rightStackView.currentItemType !== 0) { + rightStackView.currentItemType = 0 + rightStackView.pop() + } conferenceManager.creationState = 1 - conferenceInfoModel.isScheduled = scheduledSwitch.checked if( scheduledSwitch.checked){ var startDateTime = Utils.buildDate(dateField.getDate(), timeField.getTime()) + conferenceInfoModel.isScheduled = true startDateTime.setSeconds(0) conferenceInfoModel.timeZoneModel = timeZoneField.model.getAt(timeZoneField.currentIndex) conferenceInfoModel.dateTime = startDateTime - conferenceInfoModel.duration = durationField.text - } + conferenceInfoModel.duration = durationField.model[durationField.currentIndex].value + }else + conferenceInfoModel.isScheduled = false conferenceInfoModel.subject = subject.text conferenceInfoModel.description = description.text @@ -178,7 +184,8 @@ DialogPlus { spacing: 0 ColumnLayout { Layout.fillHeight: true - Layout.fillWidth: true + //Layout.fillWidth: true + Layout.preferredWidth: 3*conferenceManager.width/5 Layout.topMargin: 10 spacing: 10 @@ -188,6 +195,7 @@ DialogPlus { spacing:5 Text{ + id: subjectTitle textFormat: Text.RichText //: 'Subject' : Label of a text field about the subject of the conference text :qsTr('subjectLabel') +'*' @@ -211,7 +219,9 @@ DialogPlus { } Rectangle{ Layout.fillWidth: true - Layout.preferredHeight: scheduledSwitch.checked ? 120 : 50 + //Layout.fillHeight: true + Layout.fillHeight: conferenceInfoModel.isScheduled + Layout.preferredHeight: scheduledSwitch.checked ? parent.parent.height-subjectTitle.contentHeight-subject.contentHeight-5 : 50 Layout.rightMargin: 15 color: '#F7F7F7' ColumnLayout{ @@ -249,10 +259,11 @@ DialogPlus { visible: scheduledSwitch.checked Layout.fillWidth: true Layout.fillHeight: true + Layout.margins: 10 columns: 4 property var locale: Qt.locale() property date currentDate: new Date() - property int cellWidth: (parent.width-15)/columns + property int cellWidth: (parent.width-15-20)/columns Text{textFormat: Text.RichText; @@ -280,6 +291,8 @@ DialogPlus { text = date.toLocaleDateString(scheduleForm.locale, 'yyyy/MM/dd') } text: conferenceManager.conferenceInfoModel? conferenceManager.conferenceInfoModel.dateTime.toLocaleDateString(scheduleForm.locale, 'yyyy/MM/dd') : '' + icon: 'drop_down_custom' + showWhenEmpty: false MouseArea{ anchors.fill: parent onClicked: { @@ -304,6 +317,14 @@ DialogPlus { text = date.toLocaleTimeString(scheduleForm.locale, 'hh:mm') } text: conferenceManager.conferenceInfoModel? conferenceManager.conferenceInfoModel.dateTime.toLocaleTimeString(scheduleForm.locale, 'hh:mm') : '' + + icon: 'drop_down_custom' + showWhenEmpty: false + onEditingFinished: if(rightStackView.currentItemType === 2) { + rightStackView.currentItemType = 0 + rightStackView.pop() + } + MouseArea{ anchors.top: parent.top anchors.bottom: parent.bottom @@ -322,9 +343,20 @@ DialogPlus { } } } - NumericField{id: durationField; Layout.preferredWidth: parent.cellWidth; color: NewConferenceStyle.fields.textColor; font.weight: NewConferenceStyle.fields.weight; font.pointSize: NewConferenceStyle.fields.pointSize - text: conferenceManager.conferenceInfoModel ? conferenceManager.conferenceInfoModel.duration : '1200' + ComboBox{ + id: durationField + Layout.preferredWidth: parent.cellWidth; + currentIndex: conferenceManager.conferenceInfoModel && conferenceManager.conferenceInfoModel.duration >= 1800 ? conferenceManager.conferenceInfoModel.duration / 1800 - 1 : 0 + model: [{text:Utils.formatDuration(30*60), value:30} + ,{text:Utils.formatDuration(60*60), value:60} + ,{text:Utils.formatDuration(120*60), value:120} + ,{text:Utils.formatDuration(240*60), value:240} + ] + textRole: "text" + selectionWidth: 200 + rootItem: conferenceManager } + ComboBox{ id: timeZoneField Layout.preferredWidth: parent.cellWidth; @@ -346,6 +378,7 @@ DialogPlus { var nextStoredDate = UtilsCpp.addMinutes(new Date(), 1) dateField.setDate(nextStoredDate) timeField.setTime(nextStoredDate) + if(rightStackView.currentItemType === 2) rightStackView.currentItem.selectedTime = nextStoredDate } } Timer{ @@ -359,59 +392,59 @@ DialogPlus { } } } - } - } - ColumnLayout { - Layout.fillWidth: true - Layout.fillHeight: true - Layout.rightMargin: 15 - spacing:5 - visible: scheduledSwitch.checked - 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 : qsTr('newConferenceDescriptionTitle') - color: NewConferenceStyle.titles.textColor - font.pointSize: NewConferenceStyle.titles.pointSize - font.weight: NewConferenceStyle.titles.weight - } - TextAreaField { - id: description - Layout.fillWidth: true - Layout.fillHeight: true - //: 'Description' : Placeholder in a form about setting a description - placeholderText : qsTr('newConferenceDescriptionPlaceholder') - text: conferenceManager.conferenceInfoModel ? conferenceManager.conferenceInfoModel.description : '' - Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus() - TooltipArea{ - //: 'This description will describe the conference' : Explanation about the description of the conference - text : qsTr('newConferenceDescriptionTooltip') + + ColumnLayout { + Layout.fillWidth: true + Layout.fillHeight: true + Layout.bottomMargin: 10 + Layout.rightMargin: 15 + Layout.leftMargin: 5 + spacing:5 + visible: scheduledSwitch.checked + 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 : qsTr('newConferenceDescriptionTitle') + color: NewConferenceStyle.titles.textColor + font.pointSize: NewConferenceStyle.titles.pointSize + font.weight: NewConferenceStyle.titles.weight + } + TextAreaField { + id: description + Layout.fillWidth: true + Layout.fillHeight: true + //: 'Description' : Placeholder in a form about setting a description + placeholderText : qsTr('newConferenceDescriptionPlaceholder') + text: conferenceManager.conferenceInfoModel ? conferenceManager.conferenceInfoModel.description : '' + Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus() + TooltipArea{ + //: 'This description will describe the conference' : Explanation about the description of the conference + text : qsTr('newConferenceDescriptionTooltip') + } + } + CheckBoxText { + id: inviteAppAccountCheckBox + //: 'Send invite via Linphone' : Label for checkbox for sending invitations with Linphone. + text: qsTr('newConferenceSendLinphoneInviteLabel') + width: parent.width + checked: true + } + CheckBoxText { + id: inviteEmailCheckBox + visible: false // TODO + //: 'Send invite via Email' : Label for checkbox for sending invitations with mailer. + text: qsTr('newConferenceSendEmailInviteLabel') + width: parent.width + } } - } - } - ColumnLayout{ - Layout.fillWidth: true - spacing: 5 - CheckBoxText { - id: inviteAppAccountCheckBox - //: 'Send invite via Linphone' : Label for checkbox for sending invitations with Linphone. - text: qsTr('newConferenceSendLinphoneInviteLabel') - width: parent.width - checked: true - } - CheckBoxText { - id: inviteEmailCheckBox - visible: false // TODO - //: 'Send invite via Email' : Label for checkbox for sending invitations with mailer. - text: qsTr('newConferenceSendEmailInviteLabel') - width: parent.width - } - } - Item{ + }// ColumnLayout + + }// Rectangle + Item{// Spacer + //visible: !scheduledSwitch.checked Layout.fillHeight: true - Layout.fillWidth: true } } @@ -421,11 +454,12 @@ DialogPlus { property int currentItemType: 0 Layout.fillHeight: true - Layout.fillWidth: true + Layout.preferredWidth: 2*conferenceManager.width/5 Layout.minimumWidth: 200 Layout.topMargin: 10 Layout.bottomMargin: 10 + clip: true // ------------------------------------------------------------------------- // See and remove selected addresses. @@ -449,6 +483,8 @@ DialogPlus { Layout.fillWidth: true Layout.topMargin: ConferenceManagerStyle.columns.selector.spacing + Layout.leftMargin: 5 + Layout.rightMargin: 5 showHeader:false isMandatory: true @@ -568,6 +604,10 @@ DialogPlus { Component{ id: timePicker TimePicker{ + onNewDate:{ + if(date != timeField.getTime()) + timeField.setTime(date) + } onClicked: { timeField.setTime(date) rightStackView.currentItemType = 0