From 3b64a8c4ae408ea56b8a9732eeefce99554e3ad1 Mon Sep 17 00:00:00 2001 From: Gaelle Braud Date: Fri, 29 Mar 2024 11:18:19 +0100 Subject: [PATCH] Ui fixes, add participants panel, admin status, conf edition --- Linphone/core/conference/ConferenceCore.cpp | 11 +- Linphone/core/conference/ConferenceCore.hpp | 9 +- .../core/conference/ConferenceInfoList.cpp | 2 +- Linphone/core/participant/ParticipantCore.cpp | 27 +- Linphone/core/participant/ParticipantCore.hpp | 2 +- Linphone/core/participant/ParticipantList.cpp | 46 +- Linphone/core/participant/ParticipantList.hpp | 6 +- .../core/participant/ParticipantProxy.cpp | 43 +- .../core/participant/ParticipantProxy.hpp | 3 +- Linphone/model/conference/ConferenceModel.cpp | 8 +- Linphone/model/conference/ConferenceModel.hpp | 5 +- .../model/participant/ParticipantModel.cpp | 1 - Linphone/view/App/CallsWindow.qml | 496 ++++++++++-------- Linphone/view/App/Layout/MainLayout.qml | 2 +- Linphone/view/Item/Button.qml | 15 +- Linphone/view/Item/Call/CallContactsLists.qml | 76 +-- .../view/Item/Call/OngoingCallRightPanel.qml | 115 +++- Linphone/view/Item/Contact/ContactsList.qml | 10 +- Linphone/view/Item/Meeting/MeetingList.qml | 9 +- .../Participant/ParticipantDeviceList.qml | 4 - .../view/Item/Participant/ParticipantList.qml | 4 - .../Layout/Meeting/AddParticipantsLayout.qml | 13 +- Linphone/view/Page/Main/AbstractMainPage.qml | 17 +- Linphone/view/Page/Main/ContactPage.qml | 4 + Linphone/view/Page/Main/MeetingPage.qml | 338 ++++-------- 25 files changed, 654 insertions(+), 612 deletions(-) diff --git a/Linphone/core/conference/ConferenceCore.cpp b/Linphone/core/conference/ConferenceCore.cpp index 26a656458..62d374eca 100644 --- a/Linphone/core/conference/ConferenceCore.cpp +++ b/Linphone/core/conference/ConferenceCore.cpp @@ -38,6 +38,11 @@ ConferenceCore::ConferenceCore(const std::shared_ptr &conf mustBeInLinphoneThread(getClassName()); mConferenceModel = ConferenceModel::create(conference); mSubject = Utils::coreStringToAppString(conference->getSubject()); + mParticipantDeviceCount = conference->getParticipantDeviceList().size(); + auto me = conference->getMe(); + if (me) { + mMe = ParticipantCore::create(me); + } } ConferenceCore::~ConferenceCore() { mustBeInMainThread("~" + getClassName()); @@ -77,7 +82,7 @@ Q_INVOKABLE qint64 ConferenceCore::getElapsedSeconds() const { // std::list> // getParticipantList() const; // SDK exclude me. We want to get ALL participants. int ConferenceCore::getParticipantDeviceCount() const { - return 0; + return mParticipantDeviceCount + 1; } void ConferenceCore::setIsReady(bool state) { @@ -100,6 +105,10 @@ ParticipantDeviceGui *ConferenceCore::getActiveSpeakerGui() const { return new ParticipantDeviceGui(mActiveSpeaker); } +ParticipantGui *ConferenceCore::getMeGui() const { + return new ParticipantGui(mMe); +} + void ConferenceCore::setActiveSpeaker(const QSharedPointer &device) { if (mActiveSpeaker != device) { mActiveSpeaker = device; diff --git a/Linphone/core/conference/ConferenceCore.hpp b/Linphone/core/conference/ConferenceCore.hpp index 753661424..2e6c78262 100644 --- a/Linphone/core/conference/ConferenceCore.hpp +++ b/Linphone/core/conference/ConferenceCore.hpp @@ -21,8 +21,10 @@ #ifndef CONFERENCE_CORE_H_ #define CONFERENCE_CORE_H_ +#include "core/participant/ParticipantCore.hpp" #include "core/participant/ParticipantDeviceCore.hpp" #include "core/participant/ParticipantDeviceGui.hpp" +#include "core/participant/ParticipantGui.hpp" #include "model/conference/ConferenceModel.hpp" #include "tool/LinphoneEnums.hpp" #include "tool/thread/SafeConnection.hpp" @@ -36,11 +38,12 @@ class ConferenceCore : public QObject, public AbstractObject { public: Q_PROPERTY(QString subject READ getSubject NOTIFY subjectChanged) Q_PROPERTY(QDateTime startDate READ getStartDate CONSTANT) - // Q_PROPERTY(ParticipantListModel* participants READ getParticipantListModel CONSTANT) + // Q_PROPERTY(ParticipantDeviceList *participantDevices READ getParticipantDeviceList CONSTANT) // Q_PROPERTY(ParticipantModel* localParticipant READ getLocalParticipant NOTIFY localParticipantChanged) Q_PROPERTY(bool isReady MEMBER mIsReady WRITE setIsReady NOTIFY isReadyChanged) Q_PROPERTY(int participantDeviceCount READ getParticipantDeviceCount NOTIFY participantDeviceCountChanged) Q_PROPERTY(ParticipantDeviceGui *activeSpeaker READ getActiveSpeakerGui NOTIFY activeSpeakerChanged) + Q_PROPERTY(ParticipantGui *me READ getMeGui) // Should be call from model Thread. Will be automatically in App thread after initialization static QSharedPointer create(const std::shared_ptr &conference); @@ -57,9 +60,11 @@ public: // ParticipantListModel *getParticipantListModel() const; // std::list> // getParticipantList() const; // SDK exclude me. We want to get ALL participants. + // void getParticipantDeviceList() const; int getParticipantDeviceCount() const; ParticipantDeviceCore *getActiveSpeaker() const; ParticipantDeviceGui *getActiveSpeakerGui() const; + ParticipantGui *getMeGui() const; void setActiveSpeaker(const QSharedPointer &device); void setIsReady(bool state); @@ -78,6 +83,8 @@ private: QSharedPointer> mConferenceModelConnection; std::shared_ptr mConferenceModel; QSharedPointer mActiveSpeaker; + QSharedPointer mMe; + int mParticipantDeviceCount = 0; bool mIsReady = false; QString mSubject; diff --git a/Linphone/core/conference/ConferenceInfoList.cpp b/Linphone/core/conference/ConferenceInfoList.cpp index 0292b99c0..aa3ccf968 100644 --- a/Linphone/core/conference/ConferenceInfoList.cpp +++ b/Linphone/core/conference/ConferenceInfoList.cpp @@ -120,7 +120,7 @@ ConferenceInfoList::get(std::shared_ptr conferenceInfo QSharedPointer ConferenceInfoList::build(const std::shared_ptr &conferenceInfo) const { auto me = CoreModel::getInstance()->getCore()->getDefaultAccount()->getParams()->getIdentityAddress(); - qDebug() << "[CONFERENCEINFOLIST] looking for me " << me->asStringUriOnly(); + // qDebug() << "[CONFERENCEINFOLIST] looking for me " << me->asStringUriOnly(); std::list> participants = conferenceInfo->getParticipantInfos(); bool haveMe = conferenceInfo->getOrganizer()->weakEqual(me); if (!haveMe) diff --git a/Linphone/core/participant/ParticipantCore.cpp b/Linphone/core/participant/ParticipantCore.cpp index 0f8387d44..32ed32cad 100644 --- a/Linphone/core/participant/ParticipantCore.cpp +++ b/Linphone/core/participant/ParticipantCore.cpp @@ -41,18 +41,21 @@ QSharedPointer ParticipantCore::create(const std::shared_ptr
  • &participant) : QObject(nullptr) { App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership); mParticipantModel = Utils::makeQObject_ptr(participant); - mAdminStatus = participant->isAdmin(); - mSipAddress = Utils::coreStringToAppString(participant->getAddress()->asStringUriOnly()); - mCreationTime = QDateTime::fromSecsSinceEpoch(participant->getCreationTime()); - mDisplayName = Utils::coreStringToAppString(participant->getAddress()->getDisplayName()); - if (mDisplayName.isEmpty()) mDisplayName = Utils::coreStringToAppString(participant->getAddress()->getUsername()); - for (auto &device : participant->getDevices()) { - auto name = Utils::coreStringToAppString(device->getName()); - auto address = Utils::coreStringToAppString(device->getAddress()->asStringUriOnly()); - QVariantMap map; - map.insert("name", name); - map.insert("address", address); - mParticipantDevices.append(map); + if (participant) { + mAdminStatus = participant->isAdmin(); + mSipAddress = Utils::coreStringToAppString(participant->getAddress()->asStringUriOnly()); + mCreationTime = QDateTime::fromSecsSinceEpoch(participant->getCreationTime()); + mDisplayName = Utils::coreStringToAppString(participant->getAddress()->getDisplayName()); + if (mDisplayName.isEmpty()) + mDisplayName = Utils::coreStringToAppString(participant->getAddress()->getUsername()); + for (auto &device : participant->getDevices()) { + auto name = Utils::coreStringToAppString(device->getName()); + auto address = Utils::coreStringToAppString(device->getAddress()->asStringUriOnly()); + QVariantMap map; + map.insert("name", name); + map.insert("address", address); + mParticipantDevices.append(map); + } } // App::getInstance()->mEngine->setObjectOwnership(mParticipantDevices.get(), // QQmlEngine::CppOwnership); // Managed by QSharedPointer diff --git a/Linphone/core/participant/ParticipantCore.hpp b/Linphone/core/participant/ParticipantCore.hpp index ff675f588..8e0873a40 100644 --- a/Linphone/core/participant/ParticipantCore.hpp +++ b/Linphone/core/participant/ParticipantCore.hpp @@ -95,7 +95,7 @@ signals: void creationTimeChanged(); void displayNameChanged(); - void lStartInvitation(const int &secs); + void lStartInvitation(const int &secs = 30); void lSetIsAdmin(bool status); void invitationTimeout(ParticipantCore *model); diff --git a/Linphone/core/participant/ParticipantList.cpp b/Linphone/core/participant/ParticipantList.cpp index 003fad24a..f66f1fba9 100644 --- a/Linphone/core/participant/ParticipantList.cpp +++ b/Linphone/core/participant/ParticipantList.cpp @@ -245,6 +245,45 @@ void ParticipantList::remove(ParticipantCore *participant) { } } +void ParticipantList::addAddress(const QString &address) { + + if (!contains(address)) { + QSharedPointer participant = QSharedPointer::create(nullptr); + connect(participant.get(), &ParticipantCore::invitationTimeout, this, &ParticipantList::remove); + participant->setSipAddress(address); + add(participant); + // if (mChatRoomModel && mChatRoomModel->getChatRoom()) { // Invite and wait for its creation + // participant->startInvitation(); + // mChatRoomModel->getChatRoom()->addParticipant(Utils::interpretUrl(address)); + // } + if (mConferenceModel) { + std::list> runningCallsToAdd; + mConferenceModelConnection->invokeToModel([this, address] { + auto addressToInvite = ToolModel::interpretUrl(address); + auto currentCalls = CoreModel::getInstance()->getCore()->getCalls(); + auto haveCall = std::find_if(currentCalls.begin(), currentCalls.end(), + [addressToInvite](const std::shared_ptr &call) { + return call->getRemoteAddress()->weakEqual(addressToInvite); + }); + if (haveCall == currentCalls.end()) mConferenceModel->addParticipant(addressToInvite); + }); + // else { + // runningCallsToAdd.push_back(*haveCall); + // mConferenceModel->addParticipants(runningCallsToAdd); + // } + /* + std::list> addressesToInvite; + addressesToInvite.push_back(addressToInvite); + auto callParameters = + CoreManager::getInstance()->getCore()->createCallParams(mConferenceModel->getConference()->getCall()); + mConferenceModel->getConference()->inviteParticipants(addressesToInvite, callParameters);*/ + } + emit participant->lStartInvitation(); + emit countChanged(); + // emit addressAdded(address); + } +} + // const QSharedPointer // ParticipantList::getParticipant(const std::shared_ptr &address) const { // if (address) { @@ -271,7 +310,8 @@ void ParticipantList::remove(ParticipantCore *participant) { //------------------------------------------------------------- -// void ParticipantList::setAdminStatus(const std::shared_ptr participant, const bool &isAdmin) { +// void ParticipantList::setAdminStatus(const std::shared_ptr participant, const bool +// &isAdmin) { // // if (mChatRoomModel) mChatRoomModel->getChatRoom()->setParticipantAdminStatus(participant, isAdmin); // // if (mConferenceModel) mConferenceModel->getConference()->setParticipantAdminStatus(participant, isAdmin); // } @@ -324,8 +364,8 @@ void ParticipantList::remove(ParticipantCore *participant) { // // if (participant) remove(participant.get()); // } -// void ParticipantList::onParticipantAdminStatusChanged(const std::shared_ptr &eventLog) { -// onParticipantAdminStatusChanged(eventLog->getParticipantAddress()); +// void ParticipantList::onParticipantAdminStatusChanged(const std::shared_ptr &eventLog) +// { onParticipantAdminStatusChanged(eventLog->getParticipantAddress()); // } // void ParticipantList::onParticipantAdminStatusChanged(const std::shared_ptr // &participant) { diff --git a/Linphone/core/participant/ParticipantList.hpp b/Linphone/core/participant/ParticipantList.hpp index 2fcd5ac74..f9360b747 100644 --- a/Linphone/core/participant/ParticipantList.hpp +++ b/Linphone/core/participant/ParticipantList.hpp @@ -51,6 +51,8 @@ public: // getParticipant(const std::shared_ptr &participant) const; Q_INVOKABLE void remove(ParticipantCore *participant); + void addAddress(const QString &address); + std::list> getParticipants() const; bool contains(const QString &address) const; @@ -77,8 +79,8 @@ public: // void onParticipantDeviceRemoved(const std::shared_ptr &eventLog); // void // onParticipantRegistrationSubscriptionRequested(const std::shared_ptr - // &participantAddress); void onParticipantRegistrationUnsubscriptionRequested( const std::shared_ptr &participantAddress); void onStateChanged(); + // &participantAddress); void onParticipantRegistrationUnsubscriptionRequested( const + // std::shared_ptr &participantAddress); void onStateChanged(); signals: void securityLevelChanged(); diff --git a/Linphone/core/participant/ParticipantProxy.cpp b/Linphone/core/participant/ParticipantProxy.cpp index 0d2adb2a0..96325b72e 100644 --- a/Linphone/core/participant/ParticipantProxy.cpp +++ b/Linphone/core/participant/ParticipantProxy.cpp @@ -152,41 +152,14 @@ void ParticipantProxy::setShowMe(const bool &show) { } } -// void ParticipantProxy::addAddress(const QString &address) { -// if (!participantsModel->contains(address)) { -// QSharedPointer participant = QSharedPointer::create(nullptr); -// connect(participant.get(), &ParticipantCore::invitationTimeout, this, &ParticipantProxy::removeModel); -// participant->setSipAddress(address); -// participantsModel->add(participant); -// if (mChatRoomModel && mChatRoomModel->getChatRoom()) { // Invite and wait for its creation -// participant->startInvitation(); -// mChatRoomModel->getChatRoom()->addParticipant(Utils::interpretUrl(address)); -// } -// if (mConferenceModel && mConferenceModel->getConference()) { -// auto addressToInvite = Utils::interpretUrl(address); -// std::list> runningCallsToAdd; -// auto currentCalls = CoreManager::getInstance()->getCore()->getCalls(); -// auto haveCall = std::find_if(currentCalls.begin(), currentCalls.end(), -// [addressToInvite](const std::shared_ptr &call) { -// return call->getRemoteAddress()->weakEqual(addressToInvite); -// }); -// participant->startInvitation(); -// if (haveCall == currentCalls.end()) mConferenceModel->getConference()->addParticipant(addressToInvite); -// else { -// runningCallsToAdd.push_back(*haveCall); -// mConferenceModel->getConference()->addParticipants(runningCallsToAdd); -// } -// /* -// std::list> addressesToInvite; -// addressesToInvite.push_back(addressToInvite); -// auto callParameters = -// CoreManager::getInstance()->getCore()->createCallParams(mConferenceModel->getConference()->getCall()); -// mConferenceModel->getConference()->inviteParticipants(addressesToInvite, callParameters);*/ -// } -// emit countChanged(); -// emit addressAdded(address); -// } -// } +void ParticipantProxy::addAddress(const QString &address) { + mParticipants->addAddress(address); +} + +void ParticipantProxy::addAddresses(const QStringList &addresses) { + for (auto &address : addresses) + mParticipants->addAddress(address); +} void ParticipantProxy::removeParticipant(ParticipantCore *participant) { if (participant) { diff --git a/Linphone/core/participant/ParticipantProxy.hpp b/Linphone/core/participant/ParticipantProxy.hpp index e01888bba..9ae9bf54e 100644 --- a/Linphone/core/participant/ParticipantProxy.hpp +++ b/Linphone/core/participant/ParticipantProxy.hpp @@ -60,7 +60,8 @@ public: void setConferenceModel(ConferenceModel *conferenceModel); void setShowMe(const bool &show); - // Q_INVOKABLE void addAddress(const QString &address); + Q_INVOKABLE void addAddress(const QString &address); + Q_INVOKABLE void addAddresses(const QStringList &addresses); Q_INVOKABLE void removeParticipant(ParticipantCore *participant); Q_INVOKABLE void setParticipantAdminStatus(ParticipantCore *participant, bool status); Q_INVOKABLE void setAddresses(ConferenceInfoModel *conferenceInfoModel); diff --git a/Linphone/model/conference/ConferenceModel.cpp b/Linphone/model/conference/ConferenceModel.cpp index 6fcf4200a..2520185d0 100644 --- a/Linphone/model/conference/ConferenceModel.cpp +++ b/Linphone/model/conference/ConferenceModel.cpp @@ -52,11 +52,11 @@ void ConferenceModel::setPaused(bool paused) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); } -void ConferenceModel::removeParticipant(std::shared_ptr p) { +void ConferenceModel::removeParticipant(const std::shared_ptr &p) { mMonitor->removeParticipant(p); } -void ConferenceModel::removeParticipant(std::shared_ptr address) { +void ConferenceModel::removeParticipant(const std::shared_ptr &address) { for (auto &p : mMonitor->getParticipantList()) { if (address->asStringUriOnly() == p->getAddress()->asStringUriOnly()) { mMonitor->removeParticipant(p); @@ -64,6 +64,10 @@ void ConferenceModel::removeParticipant(std::shared_ptr addre } } +void ConferenceModel::addParticipant(const std::shared_ptr &address) { + mMonitor->addParticipant(address); +} + void ConferenceModel::setMicrophoneMuted(bool isMuted) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); mMonitor->setMicrophoneMuted(isMuted); diff --git a/Linphone/model/conference/ConferenceModel.hpp b/Linphone/model/conference/ConferenceModel.hpp index 9bc080b3c..4863b98fc 100644 --- a/Linphone/model/conference/ConferenceModel.hpp +++ b/Linphone/model/conference/ConferenceModel.hpp @@ -51,8 +51,9 @@ public: void setPaused(bool paused); - void removeParticipant(std::shared_ptr p); - void removeParticipant(std::shared_ptr address); + void removeParticipant(const std::shared_ptr &p); + void removeParticipant(const std::shared_ptr &address); + void addParticipant(const std::shared_ptr &address); signals: void microphoneMutedChanged(bool isMuted); diff --git a/Linphone/model/participant/ParticipantModel.cpp b/Linphone/model/participant/ParticipantModel.cpp index a775253b0..e5c068f25 100644 --- a/Linphone/model/participant/ParticipantModel.cpp +++ b/Linphone/model/participant/ParticipantModel.cpp @@ -29,7 +29,6 @@ DEFINE_ABSTRACT_OBJECT(ParticipantModel) ParticipantModel::ParticipantModel(std::shared_ptr linphoneParticipant, QObject *parent) : QObject(parent) { mParticipant = linphoneParticipant; - assert(mParticipant); } ParticipantModel::~ParticipantModel() { diff --git a/Linphone/view/App/CallsWindow.qml b/Linphone/view/App/CallsWindow.qml index b3c81a23b..10f56f636 100644 --- a/Linphone/view/App/CallsWindow.qml +++ b/Linphone/view/App/CallsWindow.qml @@ -32,11 +32,17 @@ Window { property var callObj function joinConference(withVideo) { - if (!conferenceInfo || conferenceInfo.core.uri.length === 0) UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("La conférence n'a pas pu démarrer en raison d'une erreur d'uri.")) + if (!conferenceInfo || conferenceInfo.core.uri.length === 0) UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("La conférence n'a pas pu démarrer en raison d'une erreur d'uri."), mainWindow) else { callObj = UtilsCpp.createCall(conferenceInfo.core.uri, withVideo) } } + function showInformationPopup(title, description, isSuccess) { + var infoPopup = popupComp.createObject(popupLayout, {"title": title, "description": description, "isSuccess": isSuccess}) + infoPopup.index = popupLayout.popupList.length + popupLayout.popupList.push(infoPopup) + infoPopup.open() + } Connections { enabled: call != undefined && call != null @@ -372,238 +378,271 @@ Window { Layout.rightMargin: 10 * DefaultStyle.dp visible: false function replace(id) { - rightPanelStack.replace(id, Control.StackView.Immediate) + contentStackView.replace(id, Control.StackView.Immediate) } - headerContent: Text { - id: rightPanelTitle - anchors.verticalCenter: parent.verticalCenter - width: rightPanel.width - color: mainWindow.conference ? DefaultStyle.main1_500_main : DefaultStyle.main2_700 - // text: qsTr("Transfert d'appel") - font { - pixelSize: 16 * DefaultStyle.dp - weight: 800 * DefaultStyle.dp + headerStack.currentIndex: 0 + contentStackView.initialItem: callsListPanel + headerValidateButtonText: qsTr("Ajouter") + } + Component { + id: contactsListPanel + CallContactsLists { + Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Transfert d'appel") + sideMargin: 10 * DefaultStyle.dp + topMargin: 15 * DefaultStyle.dp + groupCallVisible: false + searchBarColor: DefaultStyle.grey_0 + searchBarBorderColor: DefaultStyle.grey_200 + onCallButtonPressed: (address) => { + mainWindow.call.core.lTransferCall(address) } } - Control.StackView { - id: rightPanelStack - width: parent.width - height: parent.height - initialItem: callsListPanel - Component { - id: contactsListPanel - CallContactsLists { - Control.StackView.onActivated: rightPanelTitle.text = qsTr("Transfert d'appel") - sideMargin: 10 * DefaultStyle.dp - topMargin: 15 * DefaultStyle.dp - groupCallVisible: false - searchBarColor: DefaultStyle.grey_0 - searchBarBorderColor: DefaultStyle.grey_200 - onCallButtonPressed: (address) => { - mainWindow.call.core.lTransferCall(address) - } - } + } + Component { + id: dialerPanel + ColumnLayout { + Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Dialer") + Item { + Layout.fillWidth: true + Layout.fillHeight: true } - Component { - id: dialerPanel - ColumnLayout { - Control.StackView.onActivated: rightPanelTitle.text = qsTr("Dialer") - Item { - Layout.fillWidth: true - Layout.fillHeight: true - } - SearchBar { - id: dialerTextInput - Layout.fillWidth: true - Layout.leftMargin: 10 * DefaultStyle.dp - Layout.rightMargin: 10 * DefaultStyle.dp - magnifierVisible: false - color: DefaultStyle.grey_0 - borderColor: DefaultStyle.grey_200 - placeholderText: "" - numericPad: numPad - numericPadButton.visible: false - } - Item { - Layout.fillWidth: true - Layout.preferredHeight: numPad.height - Layout.topMargin: 10 * DefaultStyle.dp - property var callObj - NumericPad { - id: numPad - width: parent.width - visible: parent.visible - closeButtonVisible: false - onLaunchCall: { - callObj = UtilsCpp.createCall(dialerTextInput.text + "@sip.linphone.org") - } - } - } - } + SearchBar { + id: dialerTextInput + Layout.fillWidth: true + Layout.leftMargin: 10 * DefaultStyle.dp + Layout.rightMargin: 10 * DefaultStyle.dp + magnifierVisible: false + color: DefaultStyle.grey_0 + borderColor: DefaultStyle.grey_200 + placeholderText: "" + numericPad: numPad + numericPadButton.visible: false } - Component { - id: callsListPanel - ColumnLayout { - Control.StackView.onActivated: rightPanelTitle.text = qsTr("Liste d'appel") - RoundedBackgroundControl { - Layout.fillWidth: true - // height: Math.min(callList.height + topPadding + bottomPadding, rightPanelStack.height) - Layout.preferredHeight: Math.min(callList.height + topPadding + bottomPadding, rightPanelStack.height) - - topPadding: 15 * DefaultStyle.dp - bottomPadding: 15 * DefaultStyle.dp - leftPadding: 15 * DefaultStyle.dp - rightPadding: 15 * DefaultStyle.dp - backgroundColor: DefaultStyle.main2_0 - - contentItem: ListView { - id: callList - model: callsModel - height: Math.min(contentHeight, rightPanelStack.height) - spacing: 15 * DefaultStyle.dp - - onCountChanged: forceLayout() - - delegate: Item { - id: callDelegate - width: callList.width - height: 45 * DefaultStyle.dp - - RowLayout { - id: delegateContent - anchors.fill: parent - anchors.leftMargin: 10 * DefaultStyle.dp - anchors.rightMargin: 10 * DefaultStyle.dp - Avatar { - id: delegateAvatar - address: modelData.core.peerAddress - Layout.preferredWidth: 45 * DefaultStyle.dp - Layout.preferredHeight: 45 * DefaultStyle.dp - } - Text { - id: delegateName - property var remoteAddress: UtilsCpp.getDisplayName(modelData.core.peerAddress) - text: remoteAddress ? remoteAddress.value : "" - Connections { - target: modelData.core - } - } - Item { - Layout.fillHeight: true - Layout.fillWidth: true - } - Text { - id: callStateText - text: modelData.core.state === LinphoneEnums.CallState.Paused - || modelData.core.state === LinphoneEnums.CallState.PausedByRemote - ? qsTr("Appel en pause") : qsTr("Appel en cours") - } - PopupButton { - id: listCallOptionsButton - Layout.preferredWidth: 24 * DefaultStyle.dp - Layout.preferredHeight: 24 * DefaultStyle.dp - Layout.alignment: Qt.AlignRight - - popup.contentItem: ColumnLayout { - spacing: 0 - Control.Button { - background: Item {} - contentItem: RowLayout { - Image { - source: modelData.core.state === LinphoneEnums.CallState.Paused - || modelData.core.state === LinphoneEnums.CallState.PausedByRemote - ? AppIcons.phone : AppIcons.pause - sourceSize.width: 32 * DefaultStyle.dp - sourceSize.height: 32 * DefaultStyle.dp - Layout.preferredWidth: 32 * DefaultStyle.dp - Layout.preferredHeight: 32 * DefaultStyle.dp - fillMode: Image.PreserveAspectFit - } - Text { - text: modelData.core.state === LinphoneEnums.CallState.Paused - || modelData.core.state === LinphoneEnums.CallState.PausedByRemote - ? qsTr("Reprendre l'appel") : qsTr("Mettre en pause") - color: DefaultStyle.main2_500main - Layout.preferredWidth: metrics.width - } - TextMetrics { - id: metrics - text: qsTr("Reprendre l'appel") - } - Item { - Layout.fillWidth: true - } - } - onClicked: modelData.core.lSetPaused(!modelData.core.paused) - } - Control.Button { - background: Item {} - contentItem: RowLayout { - EffectImage { - imageSource: AppIcons.endCall - colorizationColor: DefaultStyle.danger_500main - width: 32 * DefaultStyle.dp - height: 32 * DefaultStyle.dp - } - Text { - color: DefaultStyle.danger_500main - text: qsTr("Terminer l'appel") - } - Item { - Layout.fillWidth: true - } - } - onClicked: mainWindow.endCall(modelData) - } - } - } - } - - // MouseArea{ - // anchors.fill: delegateLayout - // onClicked: { - // callsModel.currentCall = modelData - // } - // } - } - } - } - Item { - Layout.fillHeight: true - } - } - } - Component { - id: settingsPanel - InCallSettingsPanel { - Control.StackView.onActivated: rightPanelTitle.text = qsTr("Paramètres") - call: mainWindow.call - } - } - Component { - id: participantListPanel - StackLayout { - id: participantsStack - currentIndex: 0 - Control.StackView.onActivated: rightPanelTitle.text = qsTr("Participants (%1)").arg(count) - onCurrentIndexChanged: { - if (index === 0) rightPanelTitle.text = qsTr("Participants (%1)").arg(count) - else rightPanelTitle.text = qsTr("Ajouter des participants") - } - ParticipantList { - call: mainWindow.call - onCountChanged: if (Control.StackView.status === Control.StackView.Active) { - rightPanelTitle.text = qsTr("Participants (%1)").arg(count) - } - onAddParticipantRequested: participantsStack.currentIndex = 1 - } - AddParticipantsLayout { - conferenceInfoGui: mainWindow.conferenceInfo + Item { + Layout.fillWidth: true + Layout.preferredHeight: numPad.height + Layout.topMargin: 10 * DefaultStyle.dp + property var callObj + NumericPad { + id: numPad + width: parent.width + visible: parent.visible + closeButtonVisible: false + onLaunchCall: { + callObj = UtilsCpp.createCall(dialerTextInput.text + "@sip.linphone.org") } } } } } + Component { + id: callsListPanel + ColumnLayout { + Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Liste d'appel") + RoundedBackgroundControl { + Layout.fillWidth: true + Layout.preferredHeight: Math.min(callList.implicitHeight + topPadding + bottomPadding, rightPanel.height) + + topPadding: 15 * DefaultStyle.dp + bottomPadding: 15 * DefaultStyle.dp + leftPadding: 15 * DefaultStyle.dp + rightPadding: 15 * DefaultStyle.dp + backgroundColor: mainWindow.conference ? DefaultStyle.grey_0 : DefaultStyle.main2_0 + + contentItem: ListView { + id: callList + model: callsModel + implicitHeight: contentHeight// Math.min(contentHeight, rightPanel.height) + spacing: 15 * DefaultStyle.dp + clip: true + onCountChanged: forceLayout() + + delegate: Item { + id: callDelegate + width: callList.width + height: 45 * DefaultStyle.dp + + RowLayout { + id: delegateContent + anchors.fill: parent + anchors.leftMargin: 10 * DefaultStyle.dp + anchors.rightMargin: 10 * DefaultStyle.dp + Avatar { + id: delegateAvatar + address: modelData.core.peerAddress + Layout.preferredWidth: 45 * DefaultStyle.dp + Layout.preferredHeight: 45 * DefaultStyle.dp + } + Text { + id: delegateName + property var remoteAddress: UtilsCpp.getDisplayName(modelData.core.peerAddress) + text: remoteAddress ? remoteAddress.value : "" + Connections { + target: modelData.core + } + } + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + Text { + id: callStateText + text: modelData.core.state === LinphoneEnums.CallState.Paused + || modelData.core.state === LinphoneEnums.CallState.PausedByRemote + ? qsTr("Appel en pause") : qsTr("Appel en cours") + } + PopupButton { + id: listCallOptionsButton + Layout.preferredWidth: 24 * DefaultStyle.dp + Layout.preferredHeight: 24 * DefaultStyle.dp + Layout.alignment: Qt.AlignRight + + popup.contentItem: ColumnLayout { + spacing: 0 + Control.Button { + background: Item {} + contentItem: RowLayout { + Image { + source: modelData.core.state === LinphoneEnums.CallState.Paused + || modelData.core.state === LinphoneEnums.CallState.PausedByRemote + ? AppIcons.phone : AppIcons.pause + sourceSize.width: 32 * DefaultStyle.dp + sourceSize.height: 32 * DefaultStyle.dp + Layout.preferredWidth: 32 * DefaultStyle.dp + Layout.preferredHeight: 32 * DefaultStyle.dp + fillMode: Image.PreserveAspectFit + } + Text { + text: modelData.core.state === LinphoneEnums.CallState.Paused + || modelData.core.state === LinphoneEnums.CallState.PausedByRemote + ? qsTr("Reprendre l'appel") : qsTr("Mettre en pause") + color: DefaultStyle.main2_500main + Layout.preferredWidth: metrics.width + } + TextMetrics { + id: metrics + text: qsTr("Reprendre l'appel") + } + Item { + Layout.fillWidth: true + } + } + onClicked: modelData.core.lSetPaused(!modelData.core.paused) + } + Control.Button { + background: Item {} + contentItem: RowLayout { + EffectImage { + imageSource: AppIcons.endCall + colorizationColor: DefaultStyle.danger_500main + width: 32 * DefaultStyle.dp + height: 32 * DefaultStyle.dp + } + Text { + color: DefaultStyle.danger_500main + text: qsTr("Terminer l'appel") + } + Item { + Layout.fillWidth: true + } + } + onClicked: mainWindow.endCall(modelData) + } + } + } + } + + // MouseArea{ + // anchors.fill: delegateLayout + // onClicked: { + // callsModel.currentCall = modelData + // } + // } + } + } + } + Item { + Layout.fillHeight: true + } + } + } + Component { + id: settingsPanel + InCallSettingsPanel { + Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Paramètres") + call: mainWindow.call + } + } + Component { + id: participantListPanel + Control.StackView { + id: participantsStack + initialItem: participantListComp + // Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Participants (%1)").arg(participantList.count) + onCurrentItemChanged: rightPanel.headerStack.currentIndex = currentItem.Control.StackView.index + property list selectedParticipants + signal participantAdded() + + Connections { + target: rightPanel + onReturnRequested: participantsStack.pop() + } + + Component { + id: participantListComp + ParticipantList { + id: participantList + call: mainWindow.call + onAddParticipantRequested: participantsStack.push(addParticipantComp) + onCountChanged: if (participantsStack.Control.StackView.status === Control.StackView.Active && participantsStack.currentItem == participantList) { + rightPanel.headerTitleText = qsTr("Participants (%1)").arg(count) + } + Connections { + target: participantsStack + onCurrentItemChanged: { + console.log("changing title", participantsStack.currentItem == participantList) + if (participantsStack.currentItem == participantList) rightPanel.headerTitleText = qsTr("Participants (%1)").arg(participantList.count) + } + } + Connections { + target: rightPanel + // TODO : chercher comment relier ces infos pour faire le add des participants + onValidateRequested: { + participantList.model.addAddresses(participantsStack.selectedParticipants) + participantsStack.pop() + participantsStack.participantAdded() + } + } + } + } + Component { + id: addParticipantComp + AddParticipantsLayout { + id: addParticipantLayout + titleLayout.visible: false + onSelectedParticipantsCountChanged: { + if (participantsStack.Control.StackView.status === Control.StackView.Active && Control.StackView.visible) { + rightPanel.headerSubtitleText = qsTr("%1 participant%2 sélectionné").arg(selectedParticipants.length).arg(selectedParticipants.length > 1 ? "s" : "") + } + participantsStack.selectedParticipants = selectedParticipants + } + Connections { + target: participantsStack + onCurrentItemChanged: { + if (participantsStack.currentItem == addParticipantLayout) { + rightPanel.headerTitleText = qsTr("Ajouter des participants") + rightPanel.headerSubtitleText = qsTr("%1 participant%2 sélectionné").arg(addParticipantLayout.selectedParticipants.length).arg(addParticipantLayout.selectedParticipants.length > 1 ? "s" : "") + } + } + onParticipantAdded: { + addParticipantLayout.clearSelectedParticipants() + } + } + } + } + } + } + } Component { id: waitingRoom @@ -805,6 +844,7 @@ Window { onCheckedChanged: mainWindow.call.core.lSetMicrophoneMuted(!mainWindow.call.core.microphoneMuted) } CheckableButton { + visible: mainWindow.conference iconUrl: AppIcons.usersTwo checked: mainWindow.call && mainWindow.call.core.microphoneMuted checkedColor: DefaultStyle.main2_400 @@ -830,7 +870,7 @@ Window { icon.source: AppIcons.more background: Rectangle { anchors.fill: moreOptionsButton - color: moreOptionsButton.enabled + color: moreOptionsButton.enabled ? moreOptionsButton.checked ? DefaultStyle.grey_0 : DefaultStyle.grey_500 @@ -838,7 +878,13 @@ Window { radius: 40 * DefaultStyle.dp } popup.x: width/2 - popup.y: y - popup.height + height/4 + Connections { + target: moreOptionsButton.popup + onOpened: { + console.log("y", moreOptionsButton.y, moreOptionsButton.popup.y, moreOptionsButton.popup.height) + moreOptionsButton.popup.y = - moreOptionsButton.popup.height + moreOptionsButton.height/4 + } + } popup.contentItem: ColumnLayout { id: optionsList spacing: 10 * DefaultStyle.dp diff --git a/Linphone/view/App/Layout/MainLayout.qml b/Linphone/view/App/Layout/MainLayout.qml index 0b5acf75a..33da60eb7 100644 --- a/Linphone/view/App/Layout/MainLayout.qml +++ b/Linphone/view/App/Layout/MainLayout.qml @@ -178,7 +178,7 @@ Item { rightMargin: 15 * DefaultStyle.dp initialHeadersVisible: false contactMenuVisible: false - actionMenuVisible: true + actionLayoutVisible: true model: MagicSearchProxy { searchText: magicSearchBar.text.length === 0 ? "*" : magicSearchBar.text aggregationFlag: LinphoneEnums.MagicSearchAggregation.Friend diff --git a/Linphone/view/Item/Button.qml b/Linphone/view/Item/Button.qml index 8dc82e144..0bdf65c64 100644 --- a/Linphone/view/Item/Button.qml +++ b/Linphone/view/Item/Button.qml @@ -65,14 +65,13 @@ Control.Button { } component ButtonText: Text { - visible: mainItem.text != undefined horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter width: mainItem.text != undefined ? implicitWidth : 0 height: implicitHeight wrapMode: Text.WrapAnywhere - Layout.fillWidth: true - Layout.fillHeight: true + // Layout.fillWidth: true + // Layout.fillHeight: true text: mainItem.text maximumLineCount: 1 color: inversedColors ? mainItem.color : mainItem.textColor @@ -86,9 +85,8 @@ Control.Button { } component ButtonImage: EffectImage { - visible: mainItem.icon.source != undefined - Layout.fillWidth: true - Layout.fillHeight: true + // Layout.fillWidth: true + // Layout.fillHeight: true imageSource: mainItem.icon.source imageWidth: mainItem.icon.width imageHeight: mainItem.icon.height @@ -96,11 +94,12 @@ Control.Button { } contentItem: StackLayout { - currentIndex: mainItem.text.length != 0 && mainItem.icon.source != undefined + id: stacklayout + currentIndex: mainItem.text.length != 0 && mainItem.icon.source.toString().length != 0 ? 0 : mainItem.text.length != 0 ? 1 - : mainItem.icon.source != undefined + : mainItem.icon.source.toString().length != 0 ? 2 : 3 diff --git a/Linphone/view/Item/Call/CallContactsLists.qml b/Linphone/view/Item/Call/CallContactsLists.qml index 74d6de7a2..ce56525f8 100644 --- a/Linphone/view/Item/Call/CallContactsLists.qml +++ b/Linphone/view/Item/Call/CallContactsLists.qml @@ -1,4 +1,4 @@ -import QtQuick 2.7 +import QtQuick import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 as Control import QtQuick.Effects @@ -160,21 +160,28 @@ Item { spacing: 25 * DefaultStyle.dp Button { visible: mainItem.groupCallVisible - Layout.fillWidth: true + Layout.preferredWidth: 320 * DefaultStyle.dp + padding: 0 background: Rectangle { - color: DefaultStyle.groupCallButtonColor + gradient: Gradient { + orientation: Gradient.Horizontal + GradientStop { position: 0.0; color: DefaultStyle.main2_100} + GradientStop { position: 1.0; color: DefaultStyle.grey_0} + } anchors.fill: parent radius: 50 * DefaultStyle.dp } contentItem: RowLayout { + anchors.verticalCenter: parent.verticalCenter Image { source: AppIcons.groupCall - Layout.preferredWidth: 35 * DefaultStyle.dp - sourceSize.width: 35 * DefaultStyle.dp + Layout.preferredWidth: 44 * DefaultStyle.dp + sourceSize.width: 44 * DefaultStyle.dp fillMode: Image.PreserveAspectFit } Text { text: "Appel de groupe" + color: DefaultStyle.grey_1000 font { pixelSize: 16 * DefaultStyle.dp weight: 800 * DefaultStyle.dp @@ -185,36 +192,38 @@ Item { } Image { source: AppIcons.rightArrow + Layout.preferredWidth: 24 * DefaultStyle.dp + Layout.preferredHeight: 24 * DefaultStyle.dp } } } // RowLayout { - // //DEBUG - // visible: searchBar.text.length > 0 - // Layout.maximumWidth: parent.width - // Layout.fillWidth: true - // Text { - // text: searchBar.text - // maximumLineCount: 1 - // elide: Text.ElideRight - // } - // Item { - // Layout.fillWidth: true - // } - // Button { - // implicitWidth: 30 * DefaultStyle.dp - // implicitHeight: 30 * DefaultStyle.dp - // background: Item { - // visible: false - // } - // icon.source: AppIcons.phone - // width: 20 * DefaultStyle.dp - // height: 20 * DefaultStyle.dp - // onClicked: { - // mainItem.callButtonPressed(searchBar.text) - // } - // } + // //DEBUG + // visible: searchBar.text.length > 0 + // Layout.maximumWidth: parent.width + // Layout.fillWidth: true + // Text { + // text: searchBar.text + // maximumLineCount: 1 + // elide: Text.ElideRight + // } + // Item { + // Layout.fillWidth: true + // } + // Button { + // implicitWidth: 30 * DefaultStyle.dp + // implicitHeight: 30 * DefaultStyle.dp + // background: Item { + // visible: false + // } + // icon.source: AppIcons.phone + // width: 20 * DefaultStyle.dp + // height: 20 * DefaultStyle.dp + // onClicked: { + // mainItem.callButtonPressed(searchBar.text) + // } + // } // } ColumnLayout { Text { @@ -227,10 +236,10 @@ Item { ContactsList{ id: contactList Layout.fillWidth: true + Layout.preferredHeight: contentHeight contactMenuVisible: false - searchBarText: searchBar.text model: MagicSearchProxy { - searchText: searchBarText.length === 0 ? "*" : searchBarText + searchText: searchBar.text.length === 0 ? "*" : searchBar.text } onSelectedContactChanged: { if (selectedContact) { @@ -266,10 +275,9 @@ Item { contactMenuVisible: false Layout.fillWidth: true Layout.fillHeight: true + Layout.preferredHeight: contentHeight initialHeadersVisible: false displayNameCapitalization: false - // Align the suggestions list to the friends ones (which contains intial column) - delegateLeftMargin: 20 * DefaultStyle.dp model: MagicSearchProxy { searchText: searchBar.text.length === 0 ? "*" : searchBar.text sourceFlags: LinphoneEnums.MagicSearchSource.All diff --git a/Linphone/view/Item/Call/OngoingCallRightPanel.qml b/Linphone/view/Item/Call/OngoingCallRightPanel.qml index ec45f514c..861953bcf 100644 --- a/Linphone/view/Item/Call/OngoingCallRightPanel.qml +++ b/Linphone/view/Item/Call/OngoingCallRightPanel.qml @@ -5,7 +5,19 @@ import Linphone Control.Page { id: mainItem - property alias headerContent: header.children + property alias headerStack: headerStack + property alias contentStackView: contentStackView + property bool closeButtonVisible: true + clip: true + + property string headerTitleText + property string headerSubtitleText + property string headerValidateButtonText + signal returnRequested() + signal validateRequested() + + topPadding: 16 * DefaultStyle.dp + leftPadding: 16 * DefaultStyle.dp background: Rectangle { width: mainItem.width @@ -32,24 +44,93 @@ Control.Page { width: pageHeader.width } } - contentItem: RowLayout { - Item { - id: header - Layout.fillWidth: true - Layout.fillHeight: true - } - Button { - id: closeButton - background: Item { - visible: false + contentItem: StackLayout { + id: headerStack + RowLayout { + Layout.alignment: Qt.AlignVCenter + Text { + text: mainItem.headerTitleText + Layout.fillWidth: true + Layout.fillHeight: true + Layout.alignment: Qt.AlignVCenter + verticalAlignment: Text.AlignVCenter + color: mainWindow.conference ? DefaultStyle.main1_500_main : DefaultStyle.main2_700 + font { + pixelSize: 16 * DefaultStyle.dp + weight: 800 * DefaultStyle.dp + } + } + Button { + id: closeButton + visible: mainItem.closeButtonVisible + background: Item { + visible: false + } + icon.source: AppIcons.closeX + Layout.preferredWidth: 24 * DefaultStyle.dp + Layout.preferredHeight: 24 * DefaultStyle.dp + icon.width: 24 * DefaultStyle.dp + icon.height: 24 * DefaultStyle.dp + onClicked: mainItem.visible = false + } + } + RowLayout { + Layout.alignment: Qt.AlignVCenter + spacing: 5 * DefaultStyle.dp + Button { + background: Item{} + icon.source: AppIcons.leftArrow + icon.width: 24 * DefaultStyle.dp + icon.height: 24 * DefaultStyle.dp + contentImageColor: DefaultStyle.main1_500_main + onClicked: mainItem.returnRequested() + } + ColumnLayout { + Layout.fillWidth: true + Layout.fillHeight: true + Text { + Layout.alignment: Qt.AlignVCenter + verticalAlignment: Text.AlignVCenter + + text: mainItem.headerTitleText + color: DefaultStyle.main1_500_main + font { + pixelSize: 16 * DefaultStyle.dp + weight: 800 * DefaultStyle.dp + } + } + Text { + Layout.alignment: Qt.AlignVCenter + verticalAlignment: Text.AlignVCenter + + text: mainItem.headerSubtitleText + color: DefaultStyle.main2_500main + font { + pixelSize: 12 * DefaultStyle.dp + weight: 300 * DefaultStyle.dp + } + } + } + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + Button { + text: mainItem.headerValidateButtonText + textSize: 13 * DefaultStyle.dp + textWeight: 600 * DefaultStyle.dp + onClicked: mainItem.validateRequested() + topPadding: 6 * DefaultStyle.dp + bottomPadding: 6 * DefaultStyle.dp + leftPadding: 12 * DefaultStyle.dp + rightPadding: 12 * DefaultStyle.dp } - icon.source: AppIcons.closeX - Layout.preferredWidth: 24 * DefaultStyle.dp - Layout.preferredHeight: 24 * DefaultStyle.dp - icon.width: 24 * DefaultStyle.dp - icon.height: 24 * DefaultStyle.dp - onClicked: mainItem.visible = false } } } + contentItem: Control.StackView { + id: contentStackView + // width: parent.width + // height: parent.height + } } diff --git a/Linphone/view/Item/Contact/ContactsList.qml b/Linphone/view/Item/Contact/ContactsList.qml index 5f20a0c93..5a4e4675e 100644 --- a/Linphone/view/Item/Contact/ContactsList.qml +++ b/Linphone/view/Item/Contact/ContactsList.qml @@ -6,7 +6,6 @@ import UtilsCpp 1.0 ListView { id: mainItem - Layout.preferredHeight: contentHeight height: contentHeight visible: contentHeight > 0 clip: true @@ -18,7 +17,7 @@ ListView { // dots popup menu property bool contactMenuVisible: true // call, video call etc menu - property bool actionMenuVisible: true + property bool actionLayoutVisible: false property bool initialHeadersVisible: true property bool displayNameCapitalization: true property bool showOnlyFavourites: false @@ -35,7 +34,6 @@ ListView { } } } - property int delegateLeftMargin: 0 currentIndex: -1 property FriendGui selectedContact: model.getAt(currentIndex) || null @@ -88,7 +86,7 @@ ListView { RowLayout { id: contactDelegate anchors.left: initial.visible ? initial.right : parent.left - anchors.leftMargin: 10 * DefaultStyle.dp + mainItem.delegateLeftMargin + anchors.leftMargin: 10 * DefaultStyle.dp anchors.right: parent.right anchors.rightMargin: 10 * DefaultStyle.dp anchors.verticalCenter: parent.verticalCenter @@ -125,14 +123,14 @@ ListView { RowLayout { id: actionsRow z: 1 - visible: mainItem.actionMenuVisible || friendPopup.visible + // visible: mainItem.actionLayoutVisible || friendPopup.visible // anchors.fill: parent anchors.right: parent.right anchors.rightMargin: 10 * DefaultStyle.dp anchors.verticalCenter: parent.verticalCenter RowLayout{ property var callObj - visible: mainItem.actionMenuVisible + visible: mainItem.actionLayoutVisible spacing: 10 * DefaultStyle.dp Button { Layout.preferredWidth: 24 * DefaultStyle.dp diff --git a/Linphone/view/Item/Meeting/MeetingList.qml b/Linphone/view/Item/Meeting/MeetingList.qml index 583d510de..9b4ddb520 100644 --- a/Linphone/view/Item/Meeting/MeetingList.qml +++ b/Linphone/view/Item/Meeting/MeetingList.qml @@ -15,7 +15,6 @@ ListView { property bool hoverEnabled: true - property int delegateLeftMargin: 0 currentIndex: -1 property var delegateButtons @@ -99,8 +98,8 @@ ListView { Rectangle { id: conferenceInfoDelegate anchors.left: dateDay.visible ? dateDay.right : parent.left - anchors.leftMargin: 10 * DefaultStyle.dp + mainItem.delegateLeftMargin - anchors.rightMargin: 25 * DefaultStyle.dp + mainItem.delegateLeftMargin + anchors.leftMargin: 10 * DefaultStyle.dp + anchors.rightMargin: 5 * DefaultStyle.dp anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter radius: 10 * DefaultStyle.dp @@ -142,8 +141,8 @@ ListView { source: conferenceInfoDelegate anchors.fill: conferenceInfoDelegate shadowEnabled: true - shadowBlur: 1.0 - shadowOpacity: 0.1 + shadowBlur: 0.8 + shadowOpacity: 0.2 } MouseArea { diff --git a/Linphone/view/Item/Participant/ParticipantDeviceList.qml b/Linphone/view/Item/Participant/ParticipantDeviceList.qml index 32bc3bbf7..34f825067 100644 --- a/Linphone/view/Item/Participant/ParticipantDeviceList.qml +++ b/Linphone/view/Item/Participant/ParticipantDeviceList.qml @@ -18,10 +18,6 @@ ListView { property CallGui call property bool hoverEnabled: true - // dots popup menu - property bool contactMenuVisible: true - // call, video call etc menu - property bool actionMenuVisible: true property bool initialHeadersVisible: true property bool displayNameCapitalization: true diff --git a/Linphone/view/Item/Participant/ParticipantList.qml b/Linphone/view/Item/Participant/ParticipantList.qml index 27fc9ede2..132031e99 100644 --- a/Linphone/view/Item/Participant/ParticipantList.qml +++ b/Linphone/view/Item/Participant/ParticipantList.qml @@ -20,10 +20,6 @@ ListView { property bool isMeAdmin: me ? me.core.isAdmin : false property bool hoverEnabled: true - // dots popup menu - property bool contactMenuVisible: true - // call, video call etc menu - property bool actionMenuVisible: true property bool initialHeadersVisible: true property bool displayNameCapitalization: true diff --git a/Linphone/view/Layout/Meeting/AddParticipantsLayout.qml b/Linphone/view/Layout/Meeting/AddParticipantsLayout.qml index 6b954aee3..dfbedead5 100644 --- a/Linphone/view/Layout/Meeting/AddParticipantsLayout.qml +++ b/Linphone/view/Layout/Meeting/AddParticipantsLayout.qml @@ -11,12 +11,20 @@ ColumnLayout { property string validateButtonText property string placeHolderText: qsTr("Rechercher des contacts") property color titleColor: DefaultStyle.main2_700 + property list selectedParticipants: contactList.selectedContacts + property int selectedParticipantsCount: selectedParticipants.length + property alias titleLayout: titleLayout property ConferenceInfoGui conferenceInfoGui signal returnRequested() - Layout.preferredWidth: 362 * DefaultStyle.dp + // Layout.preferredWidth: 362 * DefaultStyle.dp + + function clearSelectedParticipants() { + contactList.selectedContacts.clear() + } RowLayout { - Layout.preferredWidth: 362 * DefaultStyle.dp + id: titleLayout + Layout.fillWidth: true Button { background: Item{} icon.source: AppIcons.leftArrow @@ -39,6 +47,7 @@ ColumnLayout { Layout.preferredWidth: 70 * DefaultStyle.dp topPadding: 6 * DefaultStyle.dp bottomPadding: 6 * DefaultStyle.dp + enabled: contactList.selectedContacts.length != 0 // leftPadding: 12 * DefaultStyle.dp // rightPadding: 12 * DefaultStyle.dp text: mainItem.validateButtonText diff --git a/Linphone/view/Page/Main/AbstractMainPage.qml b/Linphone/view/Page/Main/AbstractMainPage.qml index 68edb8a33..34c1e86c2 100644 --- a/Linphone/view/Page/Main/AbstractMainPage.qml +++ b/Linphone/view/Page/Main/AbstractMainPage.qml @@ -14,11 +14,12 @@ Item { property string noItemButtonText property string newItemIconSource property string emptyListText + property bool showDefaultItem: true + property color rightPanelColor: DefaultStyle.grey_100 property alias leftPanelContent: leftPanel.children property alias rightPanelStackView: rightPanelStackView property alias contactEditionComp: contactEditionComp property alias rightPanel: rightPanel - property bool showDefaultItem: true signal noItemButtonPressed() signal contactEditionClosed() @@ -151,7 +152,7 @@ Item { Rectangle { id: rightPanel clip: true - color: DefaultStyle.grey_100 + color: mainItem.rightPanelColor Layout.fillWidth: true Layout.fillHeight: true StackLayout { @@ -227,11 +228,13 @@ Item { } } - Control.StackView { - id: rightPanelStackView - Layout.fillWidth: true - Layout.fillHeight: true - Layout.leftMargin: 39 * DefaultStyle.dp + Item { + Control.StackView { + id: rightPanelStackView + anchors.fill: parent + anchors.topMargin: 39 * DefaultStyle.dp + anchors.leftMargin: 39 * DefaultStyle.dp + } } // We need this component here as it is used in multiple subPages (Call and Contact pages) Component { diff --git a/Linphone/view/Page/Main/ContactPage.qml b/Linphone/view/Page/Main/ContactPage.qml index 8d82267d6..e8d826bdc 100644 --- a/Linphone/view/Page/Main/ContactPage.qml +++ b/Linphone/view/Page/Main/ContactPage.qml @@ -168,7 +168,9 @@ AbstractMainPage { id: favoriteList hoverEnabled: mainItem.leftPanelEnabled Layout.fillWidth: true + Layout.preferredHeight: contentHeight showOnlyFavourites: true + contactMenuVisible: true model: allFriends onSelectedContactChanged: { if (selectedContact) { @@ -207,7 +209,9 @@ AbstractMainPage { ContactsList{ id: contactList hoverEnabled: mainItem.leftPanelEnabled + contactMenuVisible: true Layout.fillWidth: true + Layout.preferredHeight: contentHeight searchBarText: searchBar.text model: allFriends onSelectedContactChanged: { diff --git a/Linphone/view/Page/Main/MeetingPage.qml b/Linphone/view/Page/Main/MeetingPage.qml index e5cb179c3..f227db3a5 100644 --- a/Linphone/view/Page/Main/MeetingPage.qml +++ b/Linphone/view/Page/Main/MeetingPage.qml @@ -10,19 +10,19 @@ AbstractMainPage { noItemButtonText: qsTr("Créer une réunion") emptyListText: qsTr("Aucune réunion") newItemIconSource: AppIcons.plusCircle - // rightPanel.color: DefaultStyle.grey_0 - + rightPanelColor: selectedConference ? DefaultStyle.grey_0 : DefaultStyle.grey_100 // disable left panel contact list interaction while a contact is being edited property bool leftPanelEnabled: true property ConferenceInfoGui selectedConference property int meetingListCount signal newConfCreated() + onVisibleChanged: if (visible) rightPanelStackView.push(overridenRightPanel, Control.StackView.Immediate) onSelectedConferenceChanged: { if (selectedConference) { - if (!rightPanelStackView.currentItem || rightPanelStackView.currentItem.objectName != "meetingDetail") rightPanelStackView.replace(meetingDetail, Control.StackView.Immediate) + /*if (!overridenRightPanelStackView.currentItem || overridenRightPanelStackView.currentItem.objectName != "meetingDetail") */overridenRightPanelStackView.replace(meetingDetail, Control.StackView.Immediate) } else { - if (rightPanelStackView.currentItem && rightPanelStackView.currentItem.objectName === "meetingDetail") rightPanelStackView.clear() + /*if (overridenRightPanelStackView.currentItem && overridenRightPanelStackView.currentItem.objectName === "meetingDetail")*/ overridenRightPanelStackView.clear() } } @@ -42,7 +42,7 @@ AbstractMainPage { }', mainItem) leftPanelStackView.push(createConf, {"conferenceInfoGui": confInfoGui, "isCreation": isCreation}) } else { - rightPanelStackView.push(editConf, {"conferenceInfoGui": confInfoGui, "isCreation": isCreation}) + overridenRightPanelStackView.push(editConf, {"conferenceInfoGui": confInfoGui, "isCreation": isCreation}) } } @@ -92,23 +92,25 @@ AbstractMainPage { ] } - leftPanelContent: ColumnLayout { + leftPanelContent: RowLayout { id: leftPanel Layout.fillWidth: true Layout.fillHeight: true - property int sideMargin: 25 * DefaultStyle.dp + property int sideMargin: 20 * DefaultStyle.dp ColumnLayout { // Layout.topMargin: 30 * DefaultStyle.dp - Layout.leftMargin: leftPanel.sideMargin - spacing: 30 * DefaultStyle.dp - + // Layout.leftMargin: leftPanel.sideMargin enabled: mainItem.leftPanelEnabled + spacing: 30 * DefaultStyle.dp + Layout.leftMargin: leftPanel.sideMargin + Layout.rightMargin: leftPanel.sideMargin + RowLayout { visible: leftPanelStackView.currentItem.objectName == "listLayout" Layout.fillWidth: true - Layout.rightMargin: leftPanel.sideMargin + // Layout.rightMargin: leftPanel.sideMargin Text { text: qsTr("Réunions") @@ -142,75 +144,87 @@ AbstractMainPage { initialItem: listLayout anchors.fill: parent } - Component { - id: listLayout - ColumnLayout { - property string objectName: "listLayout" - spacing: 19 * DefaultStyle.dp + } + } - SearchBar { - id: searchBar - Layout.fillWidth: true - Layout.rightMargin: leftPanel.sideMargin - placeholderText: qsTr("Rechercher une réunion") - } + Control.ScrollBar { + id: meetingsScrollbar + visible: leftPanelStackView.currentItem.objectName == "listLayout" + active: true + interactive: true + policy: Control.ScrollBar.AsNeeded + Layout.fillHeight: true + } + } - Text { - Layout.fillHeight: true - Layout.alignment: Qt.AlignHCenter - text: mainItem.emptyListText - font { - pixelSize: 16 * DefaultStyle.dp - weight: 800 * DefaultStyle.dp - } - visible: mainItem.showDefaultItem - } - - RowLayout { - MeetingList { - id: conferenceList - visible: count != 0 - hoverEnabled: mainItem.leftPanelEnabled - Layout.fillWidth: true - Layout.fillHeight: true - Layout.topMargin: 20 * DefaultStyle.dp - searchBarText: searchBar.text - onSelectedConferenceChanged: { - mainItem.selectedConference = selectedConference - } - onCountChanged: { - mainItem.meetingListCount = count - } - Connections { - target: mainItem - onNewConfCreated: { - conferenceList.forceUpdate() - } - } - Control.ScrollBar.vertical: meetingsScrollbar - } - Control.ScrollBar { - id: meetingsScrollbar - visible: leftPanelStackView.currentItem.objectName == "listLayout" - active: true - interactive: true - policy: Control.ScrollBar.AsNeeded - Layout.fillHeight: true - // anchors.top: parent.top - // anchors.bottom: parent.bottom - // anchors.right: parent.right - } + Item { + id: overridenRightPanel + Control.StackView { + id: overridenRightPanelStackView + RectangleTest{anchors.fill: parent} + width: 393 * DefaultStyle.dp + anchors.top: parent.top + // Layout.fillWidth: false + } + } + + Component { + id: listLayout + ColumnLayout { + property string objectName: "listLayout" + spacing: 19 * DefaultStyle.dp + Control.StackView.onDeactivated: { + mainItem.selectedConference = null + // mainItem.righPanelStackView.clear() + } + Control.StackView.onActivated: mainItem.selectedConference = conferenceList.selectedConference + SearchBar { + id: searchBar + Layout.fillWidth: true + placeholderText: qsTr("Rechercher une réunion") + } + + Text { + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + text: mainItem.emptyListText + font { + pixelSize: 16 * DefaultStyle.dp + weight: 800 * DefaultStyle.dp + } + visible: mainItem.showDefaultItem + } + + RowLayout { + MeetingList { + id: conferenceList + visible: count != 0 + hoverEnabled: mainItem.leftPanelEnabled + Layout.fillWidth: true + Layout.fillHeight: true + Layout.topMargin: 20 * DefaultStyle.dp + searchBarText: searchBar.text + onSelectedConferenceChanged: { + mainItem.selectedConference = selectedConference + } + onCountChanged: { + mainItem.meetingListCount = count + } + Connections { + target: mainItem + onNewConfCreated: { + conferenceList.forceUpdate() } } + Control.ScrollBar.vertical: meetingsScrollbar } } } } - Component { id: createConf MeetingSetUp { - Layout.rightMargin: leftPanel.sideMargin + id: meetingSetup onSaveSucceed: { mainItem.newConfCreated() leftPanelStackView.pop() @@ -220,7 +234,7 @@ AbstractMainPage { leftPanelStackView.pop() } onAddParticipantsRequested: { - leftPanelStackView.push(addParticipants, {"conferenceInfoGui": conferenceInfoGui, "container": leftPanelStackView}) + leftPanelStackView.push(addParticipants, {"conferenceInfoGui": meetingSetup.conferenceInfoGui, "container": leftPanelStackView}) } } } @@ -230,49 +244,43 @@ AbstractMainPage { property bool isCreation property ConferenceInfoGui conferenceInfoGui MeetingSetUp { - Layout.alignment: Qt.AlignTop - Layout.preferredWidth: 393 * DefaultStyle.dp - Layout.fillWidth: false - Layout.fillHeight: true - Layout.leftMargin: 39 * DefaultStyle.dp - Layout.topMargin: 39 * DefaultStyle.dp isCreation: parent.isCreation conferenceInfoGui: parent.conferenceInfoGui onReturnRequested: { - mainItem.rightPanelStackView.pop() + overridenRightPanelStackView.pop() } onSaveSucceed: { - mainItem.rightPanelStackView.pop() + overridenRightPanelStackView.pop() UtilsCpp.showInformationPopup(qsTr("Enregistré"), qsTr("Réunion modifiée avec succès"), true) } onAddParticipantsRequested: { - mainItem.rightPanelStackView.push(addParticipants, {"conferenceInfoGui": conferenceInfoGui, "container": mainItem.rightPanelStackView}) + overridenRightPanelStackView.push(addParticipants, {"conferenceInfoGui": conferenceInfoGui, "container": overridenRightPanelStackView}) } } } } Component { id: addParticipants - AddParticipantsLayout { - title: qsTr("Ajouter des participants") - validateButtonText: qsTr("Ajouter") - titleColor: DefaultStyle.main1_500_main + RowLayout { + id: addParticipantLayout property Control.StackView container - onReturnRequested: { - container.pop() + property ConferenceInfoGui conferenceInfoGui + AddParticipantsLayout { + conferenceInfoGui: parent.conferenceInfoGui + title: qsTr("Ajouter des participants") + validateButtonText: qsTr("Ajouter") + titleColor: DefaultStyle.main1_500_main + onReturnRequested: { + addParticipantLayout.container.pop() + } } } } Component { id: meetingDetail RowLayout { + visible: mainItem.selectedConference ColumnLayout { - Layout.preferredWidth: 393 * DefaultStyle.dp - Layout.alignment: Qt.AlignTop - Layout.fillWidth: false - Layout.fillHeight: true - Layout.leftMargin: 39 * DefaultStyle.dp - Layout.topMargin: 39 * DefaultStyle.dp spacing: 25 * DefaultStyle.dp Section { content: RowLayout { @@ -293,12 +301,13 @@ AbstractMainPage { Layout.fillWidth: true } Button { + visible: UtilsCpp.isMe(mainItem.selectedConference.core.organizerAddress) Layout.preferredWidth: 24 * DefaultStyle.dp Layout.preferredHeight: 24 * DefaultStyle.dp icon.source: AppIcons.pencil contentImageColor: DefaultStyle.main1_500_main background: Item{} - onClicked: mainItem.setUpConference(mainItem.selectedConference) //mainItem.rightPanelStackView.push(meetingEdition) + onClicked: mainItem.setUpConference(mainItem.selectedConference) } PopupButton { id: deletePopup @@ -524,149 +533,4 @@ AbstractMainPage { } } } - // Component { - // id: meetingEdition - // RowLayout { - // ColumnLayout { - // Layout.alignment: Qt.AlignTop - // Layout.preferredWidth: 393 * DefaultStyle.dp - // Layout.fillWidth: false - // Layout.fillHeight: true - // Layout.leftMargin: 39 * DefaultStyle.dp - // Layout.topMargin: 39 * DefaultStyle.dp - // spacing: 25 * DefaultStyle.dp - // Section { - // content: RowLayout { - // spacing: 8 * DefaultStyle.dp - // Button { - // Layout.preferredWidth: 24 * DefaultStyle.dp - // Layout.preferredHeight: 24 * DefaultStyle.dp - // icon.source: AppIcons.leftArrow - // contentImageColor: DefaultStyle.main1_500_main - // background: Item{} - // onClicked: mainItem.rightPanelStackView.pop() - // } - // EffectImage { - // imageSource: AppIcons.usersThree - // Layout.preferredWidth: 24 * DefaultStyle.dp - // Layout.preferredHeight: 24 * DefaultStyle.dp - // colorizationColor: DefaultStyle.main2_600 - // } - // TextInput { - // Component.onCompleted: text = mainItem.selectedConference.core.subject - // color: DefaultStyle.main2_600 - // font { - // pixelSize: 20 * DefaultStyle.dp - // weight: 800 * DefaultStyle.dp - // } - // onEditingFinished: mainItem.selectedConference.core.subject = text - // } - // Item { - // Layout.fillWidth: true - // } - // Button { - // text: qsTr("Save") - // topPadding: 6 * DefaultStyle.dp - // bottomPadding: 6 * DefaultStyle.dp - // leftPadding: 12 * DefaultStyle.dp - // rightPadding: 12 * DefaultStyle.dp - // onClicked: { - // console.log("TODO : save meeting infos") - // mainItem.selectedConference.core.save() - // mainItem.rightPanelStackView.pop(meetingDetail, Control.StackView.Immediate) - // } - // } - // } - // } - // Section { - // content: [ - // RowLayout { - // EffectImage { - // imageSource: AppIcons.clock - // Layout.preferredWidth: 24 * DefaultStyle.dp - // Layout.preferredHeight: 24 * DefaultStyle.dp - // colorizationColor: DefaultStyle.main2_600 - // } - // Text { - // text: "All the day" - // font { - // pixelSize: 14 * DefaultStyle.dp - // weighgt: 700 * DefaultStyle.dp - // } - // } - // Item{Layout.fillWidth: true} - // Switch { - // id: isAllDaySwitch - // Component.onCompleted: if (mainItem.selectedConference.core.isAllDayConf()) toggle - // onPositionChanged: if (position === 1) { - // mainItem.selectedConference.core.dateTime = UtilsCpp.createDateTime(startDate.selectedDate, 0, 0) - // mainItem.selectedConference.core.endDateTime = UtilsCpp.createDateTime(endDate.selectedDate, 23, 59) - // } - // } - // }, - // RowLayout { - // CalendarComboBox { - // id: startDate - // background: Item{} - // contentText.font.weight: 400 * DefaultStyle.dp - // Component.onCompleted: calendar.selectedDate = mainItem.selectedConference.core.dateTime - // onSelectedDateChanged: mainItem.selectedConference.core.dateTime = UtilsCpp.createDateTime(selectedDate, startHour.selectedHour, startHour.selectedMin) - // } - // Item{Layout.fillWidth: true} - // TimeComboBox { - // id: startHour - // visible: isAllDaySwitch.position === 0 - // background: Item{} - // contentText.font.weight: 400 * DefaultStyle.dp - // onSelectedHourChanged: mainItem.selectedConference.core.dateTime = UtilsCpp.createDateTime(startDate.selectedDate, selectedHour, selectedMin) - // onSelectedMinChanged: mainItem.selectedConference.core.dateTime = UtilsCpp.createDateTime(startDate.selectedDate, selectedHour, selectedMin) - - // } - // }, - // RowLayout { - // CalendarComboBox { - // id: endDate - // background: Item{} - // contentText.font.weight: 400 * DefaultStyle.dp - // Component.onCompleted: calendar.selectedDate = mainItem.selectedConference.core.endDateTime - // onSelectedDateChanged: mainItem.selectedConference.core.endDateTime = UtilsCpp.createDateTime(selectedDate, endHour.selectedHour, endHour.selectedMin) - // } - // Item{Layout.fillWidth: true} - // TimeComboBox { - // id: endHour - // visible: isAllDaySwitch.position === 0 - // background: Item{} - // contentText.font.weight: 400 * DefaultStyle.dp - // onSelectedHourChanged: mainItem.selectedConference.core.endDateTime = UtilsCpp.createDateTime(startDate.selectedDate, selectedHour, selectedMin) - // onSelectedMinChanged: mainItem.selectedConference.core.endDateTime = UtilsCpp.createDateTime(startDate.selectedDate, selectedHour, selectedMin) - // } - // }, - // ComboBox { - // id: timeZoneCbox - // Layout.fillWidth: true - // Layout.preferredHeight: 30 * DefaultStyle.dp - // hoverEnabled: true - // listView.implicitHeight: 152 * DefaultStyle.dp - // constantImageSource: AppIcons.globe - // weight: 700 * DefaultStyle.dp - // leftMargin: 0 - // currentIndex: mainItem.conferenceInfoGui ? model.getIndex(mainItem.conferenceInfoGui.core.timeZoneModel) : -1 - // background: Rectangle { - // visible: parent.hovered || parent.down - // anchors.fill: parent - // color: DefaultStyle.grey_100 - // } - // model: TimeZoneProxy{ - // } - // onCurrentIndexChanged: { - // var modelIndex = timeZoneCbox.model.index(currentIndex, 0) - // mainItem.conferenceInfoGui.core.timeZoneModel = timeZoneCbox.model.data(modelIndex, Qt.DisplayRole + 1) - // } - // }, - // ] - // } - // // Item{Layout.fillHeight: true} - // } - // } - // } }