diff --git a/linphone-app/assets/images/back_custom.svg b/linphone-app/assets/images/back_custom.svg new file mode 100644 index 000000000..ca8092ad4 --- /dev/null +++ b/linphone-app/assets/images/back_custom.svg @@ -0,0 +1,44 @@ + + + + + + diff --git a/linphone-app/assets/images/conference_layout_active_speaker.svg b/linphone-app/assets/images/conference_layout_active_speaker.svg new file mode 100644 index 000000000..499d92007 --- /dev/null +++ b/linphone-app/assets/images/conference_layout_active_speaker.svg @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/linphone-app/assets/images/conference_layout_grid.svg b/linphone-app/assets/images/conference_layout_grid.svg new file mode 100644 index 000000000..a767ee262 --- /dev/null +++ b/linphone-app/assets/images/conference_layout_grid.svg @@ -0,0 +1,636 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/linphone-app/resources.qrc b/linphone-app/resources.qrc index ceb60e381..161b54f49 100644 --- a/linphone-app/resources.qrc +++ b/linphone-app/resources.qrc @@ -13,6 +13,7 @@ assets/images/admin_selected_custom.svg assets/images/attachment_custom.svg assets/images/auto_answer_custom.svg + assets/images/back_custom.svg assets/images/burger_menu_custom.svg assets/images/calendar_participants_custom.svg assets/images/call_accept_custom.svg @@ -54,6 +55,8 @@ assets/images/collapsed_custom.svg assets/images/conference_custom.svg assets/images/conference_layout_grid_custom.svg + assets/images/conference_layout_grid.svg + assets/images/conference_layout_active_speaker.svg assets/images/contact_add_custom.svg assets/images/contact_card_photo_custom.svg assets/images/contact_custom.svg @@ -197,8 +200,10 @@ ui/modules/Common/Form/Placements/FormTableLine.qml ui/modules/Common/Form/Placements/FormTable.qml ui/modules/Common/Form/Placements/FormVGroup.qml + ui/modules/Common/Form/RadioButton.qml ui/modules/Common/Form/SearchBox.qml ui/modules/Common/Form/Slider.qml + ui/modules/Common/Form/StackView.qml ui/modules/Common/Form/StaticListForm.qml ui/modules/Common/Form/Switch.qml ui/modules/Common/Form/Tab/TabBar.qml @@ -251,8 +256,10 @@ ui/modules/Common/Styles/Form/Placements/FormTableLineStyle.qml ui/modules/Common/Styles/Form/Placements/FormTableStyle.qml ui/modules/Common/Styles/Form/Placements/FormVGroupStyle.qml + ui/modules/Common/Styles/Form/RadioButtonStyle.qml ui/modules/Common/Styles/Form/SearchBoxStyle.qml ui/modules/Common/Styles/Form/SliderStyle.qml + ui/modules/Common/Styles/Form/StackViewStyle.qml ui/modules/Common/Styles/Form/SwitchStyle.qml ui/modules/Common/Styles/Form/Tab/TabButtonStyle.qml ui/modules/Common/Styles/Form/Tab/TabContainerStyle.qml @@ -391,6 +398,9 @@ ui/views/App/Calls/CallsWindow.qml ui/views/App/Calls/Conference.qml ui/views/App/Calls/VideoConference.qml + ui/views/App/Calls/VideoConferenceActiveSpeaker.qml + ui/views/App/Calls/VideoConferenceGrid.qml + ui/views/App/Calls/VideoConferenceMenu.qml ui/views/App/Calls/Dialogs/CallSipAddress.qml ui/views/App/Calls/Dialogs/CallTransfer.qml ui/views/App/Calls/Dialogs/ConferenceManager.qml @@ -464,6 +474,7 @@ ui/views/App/Styles/Calls/CallsWindowStyle.qml ui/views/App/Styles/Calls/ConferenceStyle.qml ui/views/App/Styles/Calls/VideoConferenceStyle.qml + ui/views/App/Styles/Calls/VideoConferenceMenuStyle.qml ui/views/App/Styles/Calls/WaitingRoomStyle.qml ui/views/App/Styles/Calls/Dialogs/CallSipAddressStyle.qml ui/views/App/Styles/Calls/Dialogs/CallTransferStyle.qml diff --git a/linphone-app/src/components/call/CallModel.cpp b/linphone-app/src/components/call/CallModel.cpp index bbb5fddc0..d02b30ef2 100644 --- a/linphone-app/src/components/call/CallModel.cpp +++ b/linphone-app/src/components/call/CallModel.cpp @@ -50,12 +50,11 @@ constexpr char AutoAnswerObjectName[] = "auto-answer-timer"; } CallModel::CallModel (shared_ptr call){ - mCall = call; if(mCall) mCall->setData("call-model", *this); - updateIsInConference(); + mConferenceVideoLayout = LinphoneEnums::fromLinphone(call->getParams()->getConferenceVideoLayout()); CoreManager *coreManager = CoreManager::getInstance(); @@ -403,6 +402,7 @@ void CallModel::handleCallStateChanged (const shared_ptr &call, mWasConnected = true; } mPausedByRemote = false; + setConferenceVideoLayout(LinphoneEnums::fromLinphone(call->getParams()->getConferenceVideoLayout())); break; } case linphone::Call::State::Connected: @@ -839,6 +839,24 @@ void CallModel::prepareTransfert(shared_ptr call, const QString& std::shared_ptr CallModel::getRemoteAddress()const{ return mRemoteAddress; } + +LinphoneEnums::ConferenceLayout CallModel::getConferenceVideoLayout() const{ + return LinphoneEnums::fromLinphone(mCall->getParams()->getConferenceVideoLayout()); +} + +void CallModel::changeConferenceVideoLayout(LinphoneEnums::ConferenceLayout layout){ + shared_ptr params = CoreManager::getInstance()->getCore()->createCallParams(mCall); + params->setConferenceVideoLayout(LinphoneEnums::toLinphone(layout)); + mCall->update(params); +} + +void CallModel::setConferenceVideoLayout(LinphoneEnums::ConferenceLayout layout){ + if( mConferenceVideoLayout != layout){ + mConferenceVideoLayout = layout; + emit conferenceVideoLayoutChanged(); + } +} + // ----------------------------------------------------------------------------- CallModel::CallEncryption CallModel::getEncryption () const { diff --git a/linphone-app/src/components/call/CallModel.hpp b/linphone-app/src/components/call/CallModel.hpp index 89b997c44..ddfb7432f 100644 --- a/linphone-app/src/components/call/CallModel.hpp +++ b/linphone-app/src/components/call/CallModel.hpp @@ -26,6 +26,8 @@ #include #include "../search/SearchListener.hpp" +#include "utils/LinphoneEnums.hpp" + // ============================================================================= class ConferenceModel; class ContactModel; @@ -79,6 +81,8 @@ class CallModel : public QObject { Q_PROPERTY(QString transferAddress READ getTransferAddress WRITE setTransferAddress NOTIFY transferAddressChanged) + Q_PROPERTY(LinphoneEnums::ConferenceLayout conferenceVideoLayout READ getConferenceVideoLayout WRITE changeConferenceVideoLayout NOTIFY conferenceVideoLayoutChanged) + public: @@ -163,6 +167,10 @@ public: std::shared_ptr getRemoteAddress()const; + LinphoneEnums::ConferenceLayout getConferenceVideoLayout() const; + void changeConferenceVideoLayout(LinphoneEnums::ConferenceLayout layout); // Make a call request + void setConferenceVideoLayout(LinphoneEnums::ConferenceLayout layout); // Called from call state changed ater the new layout has been set. + static constexpr int DtmfSoundDelay = 200; std::shared_ptr mCall; @@ -193,6 +201,8 @@ signals: void fullPeerAddressChanged(); void transferAddressChanged (const QString &transferAddress); + void conferenceVideoLayoutChanged(); + public: void handleCallEncryptionChanged (const std::shared_ptr &call); void handleCallStateChanged (const std::shared_ptr &call, linphone::Call::State state); @@ -265,6 +275,7 @@ private: bool mPausedByRemote = false; bool mPausedByUser = false; bool mRecording = false; + LinphoneEnums::ConferenceLayout mConferenceVideoLayout; bool mWasConnected = false; diff --git a/linphone-app/src/components/conference/ConferenceListener.cpp b/linphone-app/src/components/conference/ConferenceListener.cpp index f4f9ab06a..a0f7ea22d 100644 --- a/linphone-app/src/components/conference/ConferenceListener.cpp +++ b/linphone-app/src/components/conference/ConferenceListener.cpp @@ -80,6 +80,10 @@ void ConferenceListener::onParticipantDeviceMediaAvailabilityChanged(const std:: qDebug() << "onParticipantDeviceMediaAvailabilityChanged: " << (int)participantDevice->getStreamAvailability(linphone::StreamType::Video) << ". Device: " << participantDevice->getAddress()->asString().c_str(); emit participantDeviceMediaAvailabilityChanged(participantDevice); } +void ConferenceListener::onParticipantDeviceIsSpeakingChanged(const std::shared_ptr & conference, const std::shared_ptr & participantDevice, bool isSpeaking) { + qDebug() << "onParticipantDeviceIsSpeakingChanged: " << participantDevice->getAddress()->asString().c_str() << ". Speaking:" << isSpeaking; + emit participantDeviceIsSpeakingChanged(participantDevice, isSpeaking); +} void ConferenceListener::onStateChanged(const std::shared_ptr & conference, linphone::Conference::State newState){ qDebug() << "onStateChanged"; emit conferenceStateChanged(newState); diff --git a/linphone-app/src/components/conference/ConferenceListener.hpp b/linphone-app/src/components/conference/ConferenceListener.hpp index 1ce633f47..5099ae52b 100644 --- a/linphone-app/src/components/conference/ConferenceListener.hpp +++ b/linphone-app/src/components/conference/ConferenceListener.hpp @@ -44,6 +44,7 @@ public: virtual void onParticipantDeviceJoined(const std::shared_ptr & conference, const std::shared_ptr & device) override; virtual void onParticipantDeviceMediaCapabilityChanged(const std::shared_ptr & conference, const std::shared_ptr & device) override; virtual void onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr & conference, const std::shared_ptr & device) override; + virtual void onParticipantDeviceIsSpeakingChanged(const std::shared_ptr & conference, const std::shared_ptr & participantDevice, bool isSpeaking) override; virtual void onStateChanged(const std::shared_ptr & conference, linphone::Conference::State newState) override; virtual void onSubjectChanged(const std::shared_ptr & conference, const std::string & subject) override; virtual void onAudioDeviceChanged(const std::shared_ptr & conference, const std::shared_ptr & audioDevice) override; @@ -58,6 +59,7 @@ signals: void participantDeviceJoined(const std::shared_ptr & participantDevice); void participantDeviceMediaCapabilityChanged(const std::shared_ptr & participantDevice); void participantDeviceMediaAvailabilityChanged(const std::shared_ptr & participantDevice); + void participantDeviceIsSpeakingChanged(const std::shared_ptr & participantDevice, bool isSpeaking); void conferenceStateChanged(linphone::Conference::State newState); void subjectChanged(const std::string & subject); }; diff --git a/linphone-app/src/components/conference/ConferenceModel.cpp b/linphone-app/src/components/conference/ConferenceModel.cpp index 0f7f932ed..a18477515 100644 --- a/linphone-app/src/components/conference/ConferenceModel.cpp +++ b/linphone-app/src/components/conference/ConferenceModel.cpp @@ -45,6 +45,7 @@ void ConferenceModel::connectTo(ConferenceListener * listener){ connect(listener, &ConferenceListener::participantDeviceJoined, this, &ConferenceModel::onParticipantDeviceJoined); connect(listener, &ConferenceListener::participantDeviceMediaCapabilityChanged, this, &ConferenceModel::onParticipantDeviceMediaCapabilityChanged); connect(listener, &ConferenceListener::participantDeviceMediaAvailabilityChanged, this, &ConferenceModel::onParticipantDeviceMediaAvailabilityChanged); + connect(listener, &ConferenceListener::participantDeviceIsSpeakingChanged, this, &ConferenceModel::onParticipantDeviceIsSpeakingChanged); connect(listener, &ConferenceListener::conferenceStateChanged, this, &ConferenceModel::onConferenceStateChanged); connect(listener, &ConferenceListener::subjectChanged, this, &ConferenceModel::onSubjectChanged); } @@ -118,6 +119,9 @@ void ConferenceModel::onParticipantDeviceMediaAvailabilityChanged(const std::sha qDebug() << "ConferenceModel::onParticipantDeviceMediaAvailabilityChanged: " << (int)participantDevice->getStreamAvailability(linphone::StreamType::Video) << ". Me devices : " << mConference->getMe()->getDevices().size(); emit participantDeviceMediaAvailabilityChanged(participantDevice); } +void ConferenceModel::onParticipantDeviceIsSpeakingChanged(const std::shared_ptr & participantDevice, bool isSpeaking){ + emit participantDeviceIsSpeakingChanged(participantDevice, isSpeaking); +} void ConferenceModel::onConferenceStateChanged(linphone::Conference::State newState){ emit conferenceStateChanged(newState); } diff --git a/linphone-app/src/components/conference/ConferenceModel.hpp b/linphone-app/src/components/conference/ConferenceModel.hpp index 85c9a462c..51bc4b4dc 100644 --- a/linphone-app/src/components/conference/ConferenceModel.hpp +++ b/linphone-app/src/components/conference/ConferenceModel.hpp @@ -55,6 +55,7 @@ public: virtual void onParticipantDeviceJoined(const std::shared_ptr & device); virtual void onParticipantDeviceMediaCapabilityChanged(const std::shared_ptr & device); virtual void onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr & device); + virtual void onParticipantDeviceIsSpeakingChanged(const std::shared_ptr & device, bool isSpeaking); virtual void onConferenceStateChanged(linphone::Conference::State newState); virtual void onSubjectChanged(const std::string& subject); //--------------------------------------------------------------------------- @@ -68,6 +69,7 @@ signals: void participantDeviceJoined(const std::shared_ptr & participantDevice); void participantDeviceMediaCapabilityChanged(const std::shared_ptr & participantDevice); void participantDeviceMediaAvailabilityChanged(const std::shared_ptr & participantDevice); + void participantDeviceIsSpeakingChanged(const std::shared_ptr & device, bool isSpeaking); void conferenceStateChanged(linphone::Conference::State newState); void subjectChanged(); diff --git a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp index aad3f46dc..2d374437f 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp @@ -38,6 +38,7 @@ ParticipantDeviceListModel::ParticipantDeviceListModel (std::shared_ptr(deviceModel); qWarning() << "Device added. Count=" << mList.count(); return true; @@ -145,7 +150,8 @@ bool ParticipantDeviceListModel::remove(std::shared_ptr(); if( device->getDevice() == deviceToRemove){ - device->setIsLeft(true); + device->updateVideoEnabled(); + //device->setIsLeft(true); removeRow(row); return true; }else @@ -310,4 +316,16 @@ void ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged(con device->updateVideoEnabled(); else onParticipantDeviceAdded(participantDevice); +} + +void ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged(const std::shared_ptr & participantDevice, bool isSpeaking){ + if( isSpeaking){ + auto device = get(participantDevice); + if( device) + emit participantSpeaking(device.get()); + } +} + +void ParticipantDeviceListModel::onParticipantDeviceSpeaking(){ + emit participantSpeaking(qobject_cast(sender())); } \ No newline at end of file diff --git a/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp b/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp index ff28f52e5..23e0940a8 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp +++ b/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp @@ -60,9 +60,12 @@ public slots: void onConferenceStateChanged(linphone::Conference::State newState); void onParticipantDeviceMediaCapabilityChanged(const std::shared_ptr & participantDevice); void onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr & participantDevice); + void onParticipantDeviceIsSpeakingChanged(const std::shared_ptr & device, bool isSpeaking); + void onParticipantDeviceSpeaking(); signals: void securityLevelChanged(std::shared_ptr device); + void participantSpeaking(ParticipantDeviceModel *speakingDevice); private: CallModel * mCallModel = nullptr; diff --git a/linphone-app/src/components/participant/ParticipantDeviceModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceModel.cpp index 333a6ece4..e2ecfdc3a 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceModel.cpp @@ -146,7 +146,7 @@ void ParticipantDeviceModel::setIsSpeaking(bool speaking){ } void ParticipantDeviceModel::updateVideoEnabled(){ - bool enabled = !mIsLeft && (mParticipantDevice && mParticipantDevice->getStreamAvailability(linphone::StreamType::Video) && + bool enabled = (mParticipantDevice && mParticipantDevice->isInConference() && mParticipantDevice->getStreamAvailability(linphone::StreamType::Video) && ( mParticipantDevice->getStreamCapability(linphone::StreamType::Video) == linphone::MediaDirection::SendRecv || mParticipantDevice->getStreamCapability(linphone::StreamType::Video) == linphone::MediaDirection::SendOnly ) @@ -158,11 +158,6 @@ void ParticipantDeviceModel::updateVideoEnabled(){ } } -void ParticipantDeviceModel::setIsLeft(bool left) { - mIsLeft = left; - updateVideoEnabled(); -} - bool ParticipantDeviceModel::isMe() const{ return mIsMe; } diff --git a/linphone-app/src/components/participant/ParticipantDeviceModel.hpp b/linphone-app/src/components/participant/ParticipantDeviceModel.hpp index e5b5f47e9..3f7b558fa 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceModel.hpp +++ b/linphone-app/src/components/participant/ParticipantDeviceModel.hpp @@ -81,7 +81,6 @@ public: void connectTo(ParticipantDeviceListener * listener); void updateVideoEnabled(); - void setIsLeft(bool left); public slots: void onSecurityLevelChanged(std::shared_ptr device); @@ -99,7 +98,6 @@ private: bool mIsVideoEnabled; bool mIsPaused = false; bool mIsSpeaking = false; - bool mIsLeft = false; std::shared_ptr mParticipantDevice; std::shared_ptr mParticipantDeviceListener; // This is passed to linpĥone object and must be in shared_ptr diff --git a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp index 02b2c5cd2..9c514fadd 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp @@ -77,6 +77,7 @@ void ParticipantDeviceProxyModel::setCallModel(CallModel * callModel){ mCallModel = callModel; auto sourceModel = new ParticipantDeviceListModel(mCallModel); connect(sourceModel, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::onCountChanged); + connect(sourceModel, &ParticipantDeviceListModel::participantSpeaking, this, &ParticipantDeviceProxyModel::participantSpeaking); setSourceModel(sourceModel); emit countChanged(); } @@ -85,6 +86,7 @@ void ParticipantDeviceProxyModel::setParticipant(ParticipantModel * participant) setFilterType(0); auto sourceModel = participant->getParticipantDevices().get(); connect(sourceModel, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::countChanged); + connect(sourceModel, &ParticipantDeviceListModel::participantSpeaking, this, &ParticipantDeviceProxyModel::participantSpeaking); setSourceModel(sourceModel); emit countChanged(); } diff --git a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp index 762e3e822..4aa173db1 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp +++ b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp @@ -58,6 +58,7 @@ public slots: signals: void callModelChanged(); void showMeChanged(); + void participantSpeaking(ParticipantDeviceModel * speakingDevice); protected: virtual bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override; diff --git a/linphone-app/src/utils/LinphoneEnums.cpp b/linphone-app/src/utils/LinphoneEnums.cpp index 87da398b6..40561e4a0 100644 --- a/linphone-app/src/utils/LinphoneEnums.cpp +++ b/linphone-app/src/utils/LinphoneEnums.cpp @@ -69,6 +69,14 @@ LinphoneEnums::CallStatus LinphoneEnums::fromLinphone(const linphone::Call::Stat return static_cast(data); } +linphone::ConferenceLayout LinphoneEnums::toLinphone(const LinphoneEnums::ConferenceLayout& layout){ + return static_cast(layout); +} + +LinphoneEnums::ConferenceLayout LinphoneEnums::fromLinphone(const linphone::ConferenceLayout& layout){ + return static_cast(layout); +} + linphone::Tunnel::Mode LinphoneEnums::toLinphone(const LinphoneEnums::TunnelMode& data){ return static_cast(data); } diff --git a/linphone-app/src/utils/LinphoneEnums.hpp b/linphone-app/src/utils/LinphoneEnums.hpp index 715a3b04b..b29d843ca 100644 --- a/linphone-app/src/utils/LinphoneEnums.hpp +++ b/linphone-app/src/utils/LinphoneEnums.hpp @@ -112,6 +112,15 @@ Q_ENUM_NS(CallStatus) linphone::Call::Status toLinphone(const LinphoneEnums::CallStatus& capability); LinphoneEnums::CallStatus fromLinphone(const linphone::Call::Status& capability); +enum ConferenceLayout { + ConferenceLayoutGrid = int(linphone::ConferenceLayout::Grid), + ConferenceLayoutActiveSpeaker = int(linphone::ConferenceLayout::ActiveSpeaker), +}; +Q_ENUM_NS(ConferenceLayout) + +linphone::ConferenceLayout toLinphone(const LinphoneEnums::ConferenceLayout& layout); +LinphoneEnums::ConferenceLayout fromLinphone(const linphone::ConferenceLayout& layout); + enum TunnelMode { TunnelModeDisable = int(linphone::Tunnel::Mode::Disable), TunnelModeEnable= int(linphone::Tunnel::Mode::Enable), diff --git a/linphone-app/ui/modules/Common/Form/RadioButton.qml b/linphone-app/ui/modules/Common/Form/RadioButton.qml new file mode 100644 index 000000000..5560d58f2 --- /dev/null +++ b/linphone-app/ui/modules/Common/Form/RadioButton.qml @@ -0,0 +1,56 @@ +import QtQuick 2.12 +import QtQuick.Layouts 1.3 +import QtQml.Models 2.12 +import QtGraphicalEffects 1.12 +import QtQuick.Controls 2.12 as Control + +import Common 1.0 +import Common.Styles 1.0 +import Linphone 1.0 + + +// ============================================================================= + +Control.RadioButton{ + id: radio + font.weight: checked ? RadioButtonStyle.selectedWeight : RadioButtonStyle.weight + font.pointSize: RadioButtonStyle.pointSize + spacing: 10 + FontMetrics{id: fontMetrics} + indicator: Rectangle { + height: fontMetrics.height - 5 + width: height + //onHeightChanged: height = fontMetrics.height - 5 + //onWidthChanged: width = fontMetrics.height - 5 + x: parent.leftPadding + y: parent.height / 2 - height / 2 + radius: width/2 + border.color: RadioButtonStyle.color + property bool checked: parent.checked + Rectangle { + width: parent.width - 8 + height: width + x: 4 + y: 4 + radius: width/2 + color: RadioButtonStyle.color + visible: parent.checked + } + } + contentItem: Text{ + text: parent.text + font: parent.font + width: parent.width - (parent.indicator.width + parent.spacing) + height: implicitHeight + y:0 + // Override unwanted auto changes + onYChanged: y = 0 + onHeightChanged: height=implicitHeight + //--------------------------------------- + color: RadioButtonStyle.color + verticalAlignment: Text.AlignVCenter + leftPadding: parent.indicator.width + parent.spacing + wrapMode: Text.WordWrap + elide: Text.ElideRight + } +} \ No newline at end of file diff --git a/linphone-app/ui/modules/Common/Form/StackView.qml b/linphone-app/ui/modules/Common/Form/StackView.qml new file mode 100644 index 000000000..1d622e6cf --- /dev/null +++ b/linphone-app/ui/modules/Common/Form/StackView.qml @@ -0,0 +1,70 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.12 as Control + +import Common 1.0 +import Common.Styles 1.0 + +import Utils 1.0 + +Control.StackView { + id: stack + clip:true + property string viewsPath + signal exit() + + readonly property alias nViews: stack.depth + + function pushView (view, properties) { + stack.push(Utils.isString(view) ? viewsPath + view + '.qml' : view,properties) + } + + function getView (index) { + return stack.get(index) + } + + function popView () { + if( nViews <= 1 ) { + stack.pop() + stack.exit() + }else + stack.pop() + } + + // ------------------------------------------------------------------------- + + popEnter: Transition { + YAnimator { + duration: StackViewStyle.stackAnimation.duration + easing.type: Easing.OutBack + from: stack.height + StackViewStyle.bottomMargin + to: 0 + } + } + + popExit: Transition { + XAnimator { + duration: StackViewStyle.stackAnimation.duration + easing.type: Easing.OutBack + from: 0 + to: stack.width + StackViewStyle.rightMargin + } + } + + pushEnter: Transition { + XAnimator { + duration: StackViewStyle.stackAnimation.duration + easing.type: Easing.OutBack + from: stack.width + StackViewStyle.rightMargin + to: 0 + } + } + + pushExit: Transition { + YAnimator { + duration: StackViewStyle.stackAnimation.duration + easing.type: Easing.OutBack + from: 0 + to: stack.height + StackViewStyle.bottomMargin + } + } + } \ No newline at end of file diff --git a/linphone-app/ui/modules/Common/Styles/Form/RadioButtonStyle.qml b/linphone-app/ui/modules/Common/Styles/Form/RadioButtonStyle.qml new file mode 100644 index 000000000..b84c3112d --- /dev/null +++ b/linphone-app/ui/modules/Common/Styles/Form/RadioButtonStyle.qml @@ -0,0 +1,19 @@ +pragma Singleton +import QtQml 2.2 +import QtQuick 2.7 + +import Units 1.0 +import ColorsList 1.0 + +// ============================================================================= + +QtObject { + property string sectionName: 'RadioButton' + property color backgroundColor: ColorsList.add(sectionName+'_bg', 'k').color + + property int height: 60 + property color color: ColorsList.add(sectionName+'_fg', 'j').color + property int weight: Font.Normal + property int selectedWeight: Font.Bold + property int pointSize: Units.dp * 12 +} diff --git a/linphone-app/ui/modules/Common/Styles/Form/StackViewStyle.qml b/linphone-app/ui/modules/Common/Styles/Form/StackViewStyle.qml new file mode 100644 index 000000000..d08417c02 --- /dev/null +++ b/linphone-app/ui/modules/Common/Styles/Form/StackViewStyle.qml @@ -0,0 +1,18 @@ +pragma Singleton +import QtQml 2.2 + +import ColorsList 1.0 + +// ============================================================================= + +QtObject { + property string sectionName: 'StackView' + property int bottomMargin: 35 + property int leftMargin: 90 + property int rightMargin: 90 + property int topMargin: 50 + + property QtObject stackAnimation: QtObject { + property int duration: 400 + } +} diff --git a/linphone-app/ui/modules/Common/Styles/qmldir b/linphone-app/ui/modules/Common/Styles/qmldir index b55f415d0..fb1e8ea95 100644 --- a/linphone-app/ui/modules/Common/Styles/qmldir +++ b/linphone-app/ui/modules/Common/Styles/qmldir @@ -14,8 +14,10 @@ singleton CheckBoxTextStyle 1.0 Form/CheckBoxTextStyle.qml singleton ComboBoxStyle 1.0 Form/ComboBoxStyle.qml singleton DroppableTextAreaStyle 1.0 Form/DroppableTextAreaStyle.qml singleton ListFormStyle 1.0 Form/ListFormStyle.qml +singleton RadioButtonStyle 1.0 Form/RadioButtonStyle.qml singleton SearchBoxStyle 1.0 Form/SearchBoxStyle.qml singleton SliderStyle 1.0 Form/SliderStyle.qml +singleton StackViewStyle 1.0 Form/StackViewStyle.qml singleton SwitchStyle 1.0 Form/SwitchStyle.qml singleton CommonItemDelegateStyle 1.0 Form/CommonItemDelegateStyle.qml singleton TransparentTextInputStyle 1.0 Form/TransparentTextInputStyle.qml diff --git a/linphone-app/ui/modules/Common/qmldir b/linphone-app/ui/modules/Common/qmldir index 71ad8f096..da5bed353 100644 --- a/linphone-app/ui/modules/Common/qmldir +++ b/linphone-app/ui/modules/Common/qmldir @@ -27,8 +27,10 @@ ListForm 1.0 Form/ListForm.qml ListItemSelector 1.0 Form/ListItemSelector.qml Mosaic 1.0 Form/Mosaic.qml MouseArea 1.0 Form/MouseArea.qml +RadioButton 1.0 Form/RadioButton.qml SearchBox 1.0 Form/SearchBox.qml Slider 1.0 Form/Slider.qml +StackView 1.0 Form/StackView.qml StaticListForm 1.0 Form/StaticListForm.qml Switch 1.0 Form/Switch.qml TransparentTextInput 1.0 Form/TransparentTextInput.qml diff --git a/linphone-app/ui/modules/Linphone/Camera/CameraItem.qml b/linphone-app/ui/modules/Linphone/Camera/CameraItem.qml index 19b56ed52..1e8fc5d95 100644 --- a/linphone-app/ui/modules/Linphone/Camera/CameraItem.qml +++ b/linphone-app/ui/modules/Linphone/Camera/CameraItem.qml @@ -22,6 +22,7 @@ Item { property bool hideCamera: false //callModel.pausedByUser property bool isPaused: false property bool isVideoEnabled: enabled && (!container.currentDevice || (container.currentDevice && container.currentDevice.videoEnabled)) + onCurrentDeviceChanged: resetActive() function resetActive(){ resetTimer.resetActive() } diff --git a/linphone-app/ui/views/App/Calls/CallsWindow.qml b/linphone-app/ui/views/App/Calls/CallsWindow.qml index 803dc09cc..26ae7ac54 100644 --- a/linphone-app/ui/views/App/Calls/CallsWindow.qml +++ b/linphone-app/ui/views/App/Calls/CallsWindow.qml @@ -261,9 +261,9 @@ Window { id: videoConference VideoConference { callModel: window.call + enabled: window.visible listCallsOpened: window.callsIsOpened onOpenListCallsRequest: mainPaned.open() - enabled: window.visible } } diff --git a/linphone-app/ui/views/App/Calls/VideoConference.qml b/linphone-app/ui/views/App/Calls/VideoConference.qml index cac836fac..9e58a50bf 100644 --- a/linphone-app/ui/views/App/Calls/VideoConference.qml +++ b/linphone-app/ui/views/App/Calls/VideoConference.qml @@ -8,6 +8,7 @@ import Common.Styles 1.0 import Linphone 1.0 import LinphoneUtils 1.0 +import LinphoneEnums 1.0 import UtilsCpp 1.0 import App.Styles 1.0 @@ -168,7 +169,7 @@ Rectangle { anchors.bottom: actionsButtons.top anchors.leftMargin: 70 - anchors.rightMargin: 70 + anchors.rightMargin: rightMenu.visible ? 70 : 15 anchors.topMargin: 15 anchors.bottomMargin: 20 onClicked: { @@ -177,81 +178,37 @@ Rectangle { +Math.floor(Math.random()*255).toString(16) +Math.floor(Math.random()*255).toString(16)}) } - /* - ParticipantDeviceProxyModel{ - id: participantDevices + Component{ + id: gridComponent + VideoConferenceGrid{ + id: grid callModel: conference.callModel - }*/ - Mosaic { - id: grid - anchors.fill: parent - squaredDisplay: true - - function setTestMode(){ - grid.clear() - gridModel.model = gridModel.defaultList - for(var i = 0 ; i < 5 ; ++i) - grid.add({color: '#'+ Math.floor(Math.random()*255).toString(16) - +Math.floor(Math.random()*255).toString(16) - +Math.floor(Math.random()*255).toString(16)}) - console.log("Setting test mode : count=" + gridModel.defaultList.count) - } - function setParticipantDevicesMode(){ - console.log("Setting participant mode : count=" + gridModel.participantDevices.count) - grid.clear() - gridModel.model = gridModel.participantDevices - } - - delegateModel: DelegateModel{ - id: gridModel - property ParticipantDeviceProxyModel participantDevices : ParticipantDeviceProxyModel { - id: participantDevices - callModel: conference.callModel - showMe: true - } - /* - property ListModel defaultList : ListModel{} - Component.onCompleted: { - if( conference.callModel ){ - grid.clear() - gridModel.model = participantDevices - } - } - model: defaultList - */ - model: participantDevices - onCountChanged: {console.log("Delegate count = "+count+"/"+participantDevices.count)} - delegate: Item{ - id: avatarCell - property ParticipantDeviceModel currentDevice: gridModel.participantDevices.getAt(index) - onCurrentDeviceChanged: { - console.log("currentDevice changed: " +currentDevice+"/"+cameraView.currentDevice + (currentDevice?", me:"+currentDevice.isMe:'')+" ["+index+"]") - if(index < 0) cameraView.enabled = false // this is a delegate destruction. We need to stop camera before Qt change its currentDevice (and then, let CameraView to delete wrong renderer) - - } - //color: 'black' /*!conference.callModel && gridModel.defaultList.get(index).color ? gridModel.defaultList.get(index).color : */ - //color: gridModel.model.get(index) && gridModel.model.get(index).color ? gridModel.model.get(index).color : '' // modelIndex is a custom index because by Mosaic modelisation, it is not accessible. - //color: $modelData.color ? $modelData.color : '' - height: grid.cellHeight - 10 - width: grid.cellWidth - 10 - Component.onCompleted: { - console.log("Completed: ["+index+"] " +(currentDevice?currentDevice.peerAddress+", isMe:"+currentDevice.isMe : '') ) - } - - CameraView{ - id: cameraView - enabled: index >=0 - anchors.fill: parent - currentDevice: avatarCell.currentDevice - isPaused: callModel.pausedByUser || avatarCell.currentDevice && avatarCell.currentDevice.isPaused //callModel.pausedByUser - onCloseRequested: grid.remove( index) - color: 'black' - } - } } } - - + Component{ + id: activeSpeakerComponent + VideoConferenceActiveSpeaker{ + id: activeSpeaker + callModel: conference.callModel + } + } + RowLayout{ + anchors.fill: parent + Loader{ + Layout.fillHeight: true + Layout.fillWidth: true + sourceComponent: conference.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutGrid ? gridComponent : activeSpeakerComponent + onSourceComponentChanged: console.log(conference.callModel.conferenceVideoLayout) + active: conference.callModel + } + VideoConferenceMenu{ + id: rightMenu + Layout.fillHeight: true + Layout.preferredWidth: 400 + callModel: conference.callModel + onClose: rightMenu.visible = !rightMenu.visible + } + } } // ------------------------------------------------------------------------- // Action Buttons. @@ -403,7 +360,7 @@ Rectangle { isCustom: true backgroundRadius: width/2 colorSet: VideoConferenceStyle.buttons.options - visible: false //TODO + onClicked: rightMenu.visible = !rightMenu.visible } } diff --git a/linphone-app/ui/views/App/Calls/VideoConferenceActiveSpeaker.qml b/linphone-app/ui/views/App/Calls/VideoConferenceActiveSpeaker.qml new file mode 100644 index 000000000..e085e6911 --- /dev/null +++ b/linphone-app/ui/views/App/Calls/VideoConferenceActiveSpeaker.qml @@ -0,0 +1,43 @@ +import QtQuick 2.7 +import QtQuick.Layouts 1.3 +import QtQml.Models 2.12 +import QtGraphicalEffects 1.12 + +import Common 1.0 +import Common.Styles 1.0 +import Linphone 1.0 +import LinphoneUtils 1.0 + +import UtilsCpp 1.0 + +import App.Styles 1.0 + + +// Temp +import 'Incall.js' as Logic +import 'qrc:/ui/scripts/Utils/utils.js' as Utils + +// ============================================================================= + +Item { + id: grid + property alias callModel: participantDevices.callModel + anchors.fill: parent + + property ParticipantDeviceProxyModel participantDevices : ParticipantDeviceProxyModel { + id: participantDevices + showMe: true + onParticipantSpeaking: cameraView.currentDevice = speakingDevice + } + + CameraView{ + id: cameraView + enabled: index >=0 + anchors.fill: parent + isPaused: callModel.pausedByUser || currentDevice && currentDevice.isPaused //callModel.pausedByUser + showCloseButton: false + // onCloseRequested: grid.remove( index) + color: 'black' + } +} + diff --git a/linphone-app/ui/views/App/Calls/VideoConferenceGrid.qml b/linphone-app/ui/views/App/Calls/VideoConferenceGrid.qml new file mode 100644 index 000000000..902b021fd --- /dev/null +++ b/linphone-app/ui/views/App/Calls/VideoConferenceGrid.qml @@ -0,0 +1,80 @@ +import QtQuick 2.7 +import QtQuick.Layouts 1.3 +import QtQml.Models 2.12 +import QtGraphicalEffects 1.12 + +import Common 1.0 +import Common.Styles 1.0 +import Linphone 1.0 +import LinphoneUtils 1.0 + +import UtilsCpp 1.0 + +import App.Styles 1.0 + + +// Temp +import 'Incall.js' as Logic +import 'qrc:/ui/scripts/Utils/utils.js' as Utils + +// ============================================================================= + +Mosaic { + id: grid + property alias callModel: participantDevices.callModel + anchors.fill: parent + squaredDisplay: true + + function setTestMode(){ + grid.clear() + gridModel.model = gridModel.defaultList + for(var i = 0 ; i < 5 ; ++i) + grid.add({color: '#'+ Math.floor(Math.random()*255).toString(16) + +Math.floor(Math.random()*255).toString(16) + +Math.floor(Math.random()*255).toString(16)}) + console.log("Setting test mode : count=" + gridModel.defaultList.count) + } + function setParticipantDevicesMode(){ + console.log("Setting participant mode : count=" + gridModel.participantDevices.count) + grid.clear() + gridModel.model = gridModel.participantDevices + } + + delegateModel: DelegateModel{ + id: gridModel + property ParticipantDeviceProxyModel participantDevices : ParticipantDeviceProxyModel { + id: participantDevices + //callModel: conference.callModel + showMe: true + } + model: participantDevices + onCountChanged: {console.log("Delegate count = "+count+"/"+participantDevices.count)} + delegate: Item{ + id: avatarCell + property ParticipantDeviceModel currentDevice: gridModel.participantDevices.getAt(index) + onCurrentDeviceChanged: { + console.log("currentDevice changed: " +currentDevice+"/"+cameraView.currentDevice + (currentDevice?", me:"+currentDevice.isMe:'')+" ["+index+"]") + if(index < 0) cameraView.enabled = false // this is a delegate destruction. We need to stop camera before Qt change its currentDevice (and then, let CameraView to delete wrong renderer) + + } + //color: 'black' /*!conference.callModel && gridModel.defaultList.get(index).color ? gridModel.defaultList.get(index).color : */ + //color: gridModel.model.get(index) && gridModel.model.get(index).color ? gridModel.model.get(index).color : '' // modelIndex is a custom index because by Mosaic modelisation, it is not accessible. + //color: $modelData.color ? $modelData.color : '' + height: grid.cellHeight - 10 + width: grid.cellWidth - 10 + Component.onCompleted: { + console.log("Completed: ["+index+"] " +(currentDevice?currentDevice.peerAddress+", isMe:"+currentDevice.isMe : '') ) + } + + CameraView{ + id: cameraView + enabled: index >=0 + anchors.fill: parent + currentDevice: avatarCell.currentDevice + isPaused: callModel.pausedByUser || avatarCell.currentDevice && avatarCell.currentDevice.isPaused //callModel.pausedByUser + onCloseRequested: grid.remove( index) + color: 'black' + } + } + } +} \ No newline at end of file diff --git a/linphone-app/ui/views/App/Calls/VideoConferenceMenu.qml b/linphone-app/ui/views/App/Calls/VideoConferenceMenu.qml new file mode 100644 index 000000000..7578181c3 --- /dev/null +++ b/linphone-app/ui/views/App/Calls/VideoConferenceMenu.qml @@ -0,0 +1,188 @@ +import QtQuick 2.12 +import QtQuick.Layouts 1.3 +import QtQml.Models 2.12 +import QtGraphicalEffects 1.12 +import QtQuick.Controls 2.12 +import Common 1.0 +import Common.Styles 1.0 +import Linphone 1.0 +import LinphoneUtils 1.0 + +import LinphoneEnums 1.0 + +import UtilsCpp 1.0 + +import App.Styles 1.0 + + +// Temp +import 'Incall.js' as Logic +import 'qrc:/ui/scripts/Utils/utils.js' as Utils + +// ============================================================================= + +Rectangle{ + id: mainItem + property CallModel callModel + signal close() + + height: 500 + width: 400 + color: "white" + radius: VideoConferenceMenuStyle.radius + ButtonGroup{id: modeGroup} + ColumnLayout{ + anchors.fill: parent +// HEADER + Borders{ + Layout.fillWidth: true + Layout.preferredHeight: Math.max(VideoConferenceMenuStyle.header.height, title.implicitHeight+20) + bottomColor: VideoConferenceMenuStyle.list.border.color + bottomWidth: VideoConferenceMenuStyle.list.border.width + RowLayout{ + anchors.fill: parent + ActionButton{ + //Layout.minimumHeight: VideoConferenceMenuStyle.buttons.back.iconSize + //Layout.minimumWidth: VideoConferenceMenuStyle.buttons.back.iconSize + backgroundRadius: width/2 + isCustom: true + colorSet: VideoConferenceMenuStyle.buttons.back + onClicked: contentsStack.pop() + visible: contentsStack.nViews > 1 + } + Text{ + id: title + text: contentsStack.currentItem.objectName == 'settingsMenu' ? 'Paramètres' : 'Modifier la mise en page' + Layout.fillWidth: true + Layout.preferredHeight: implicitHeight + horizontalAlignment: Qt.AlignCenter + color: VideoConferenceMenuStyle.header.color + font.pointSize: VideoConferenceMenuStyle.header.pointSize + font.weight: VideoConferenceMenuStyle.header.weight + wrapMode: Text.WordWrap + elide: Text.ElideRight + } + ActionButton{ + Layout.rightMargin: 10 + backgroundRadius: width/2 + isCustom: true + colorSet: VideoConferenceMenuStyle.buttons.close + onClicked: mainItem.close() + } + } + } +// CONTENT + StackView{ + id: contentsStack + initialItem: settingsMenuComponent + Layout.fillHeight: true + Layout.fillWidth: true + } + Component{ + id: settingsMenuComponent + ColumnLayout{ + property string objectName: 'settingsMenu' + Layout.fillHeight: true + Layout.fillWidth: true + Repeater{ + model: [{text: 'Modifier la mise en page', icon: VideoConferenceMenuStyle.settingsIcons.gridIcon, nextPage:layoutMenu} + ] + delegate: + Borders{ + bottomColor: VideoConferenceMenuStyle.list.border.color + bottomWidth: VideoConferenceMenuStyle.list.border.width + Layout.preferredHeight: Math.max(settingIcon.height, settingsDescription.implicitHeight) + 20 + Layout.fillWidth: true + RowLayout{ + anchors.fill: parent + Icon{ + id: settingIcon + Layout.minimumWidth: iconWidth + Layout.leftMargin: 15 + Layout.alignment: Qt.AlignVCenter + icon: modelData.icon + overwriteColor: VideoConferenceMenuStyle.list.color + iconWidth: VideoConferenceMenuStyle.settingsIcons.width + iconHeight: VideoConferenceMenuStyle.settingsIcons.height + } + Text{ + id: settingsDescription + Layout.fillWidth: true + height: implicitHeight + wrapMode: Text.WordWrap + elide: Text.ElideRight + + text: modelData.text + font.pointSize: VideoConferenceMenuStyle.list.pointSize + color: VideoConferenceMenuStyle.list.color + } + ActionButton{ + Layout.minimumWidth: iconWidth + Layout.rightMargin: 10 + Layout.alignment: Qt.AlignVCenter + backgroundRadius: width/2 + isCustom: true + colorSet: VideoConferenceMenuStyle.buttons.next + } + } + MouseArea{ + anchors.fill: parent + onClicked: contentsStack.push(modelData.nextPage) + } + } + } + Item{// Spacer + Layout.fillWidth: true + Layout.fillHeight: true + } + } + } + Component{ + id: layoutMenu + ColumnLayout{ + Layout.fillHeight: true + Layout.fillWidth: true + Repeater{ + model: [{text: 'Mode mosaïque', icon: VideoConferenceMenuStyle.modeIcons.gridIcon, value:LinphoneEnums.ConferenceLayoutGrid} + , {text: 'Mode présentateur', icon: VideoConferenceMenuStyle.modeIcons.activeSpeakerIcon, value:LinphoneEnums.ConferenceLayoutActiveSpeaker} + ] + delegate: + Borders{ + bottomColor: VideoConferenceMenuStyle.list.border.color + bottomWidth: VideoConferenceMenuStyle.list.border.width + Layout.preferredHeight: Math.max(layoutIcon.height, radio.contentItem.implicitHeight) + 20 + Layout.fillWidth: true + RowLayout{ + anchors.fill: parent + + RadioButton{ + id: radio + Layout.fillWidth: true + Layout.leftMargin: 15 + Layout.preferredHeight: contentItem.implicitHeight + Layout.alignment: Qt.AlignVCenter + ButtonGroup.group: modeGroup + checked: mainItem.callModel ? modelData.value == mainItem.callModel.conferenceVideoLayout : false + text: modelData.text + onClicked: mainItem.callModel.conferenceVideoLayout = modelData.value + } + Icon{ + id: layoutIcon + Layout.minimumWidth: iconWidth + Layout.rightMargin: 10 + Layout.alignment: Qt.AlignVCenter + icon: modelData.icon + iconWidth: VideoConferenceMenuStyle.modeIcons.width + iconHeight: VideoConferenceMenuStyle.modeIcons.height + } + } + } + } + Item{// Spacer + Layout.fillWidth: true + Layout.fillHeight: true + } + } + } + } +} diff --git a/linphone-app/ui/views/App/Main/Assistant.qml b/linphone-app/ui/views/App/Main/Assistant.qml index 42ae6c143..07f3cb7c2 100644 --- a/linphone-app/ui/views/App/Main/Assistant.qml +++ b/linphone-app/ui/views/App/Main/Assistant.qml @@ -1,95 +1,41 @@ import QtQuick 2.7 -import QtQuick.Controls 2.2 import QtQuick.Window 2.2 import Utils 1.0 +import Common 1.0 import App.Styles 1.0 // ============================================================================= Item { - id: assistant - - readonly property string viewsPath: 'qrc:/ui/views/App/Main/Assistant/' - readonly property alias nViews: stack.depth - - // --------------------------------------------------------------------------- - - function pushView (view, properties) { - stack.push( - Utils.isString(view) ? viewsPath + view + '.qml' : view, - properties - ) - } - - function getView (index) { - return stack.get(index) - } - - function popView () { - if( nViews <= 1 ) { - stack.pop() - window.setView('Home') - }else - stack.pop() - } - - // --------------------------------------------------------------------------- - - Rectangle { - anchors.fill: parent - color: AssistantStyle.color - } - - // --------------------------------------------------------------------------- - - StackView { - id: stack - clip:true - - anchors { - fill: parent - } - - initialItem: assistant.viewsPath + 'AssistantHome.qml' - - // ------------------------------------------------------------------------- - - popEnter: Transition { - YAnimator { - duration: AssistantStyle.stackAnimation.duration - easing.type: Easing.OutBack - from: stack.height + AssistantStyle.bottomMargin - to: 0 - } - } - - popExit: Transition { - XAnimator { - duration: AssistantStyle.stackAnimation.duration - easing.type: Easing.OutBack - from: 0 - to: stack.width + AssistantStyle.rightMargin - } - } - - pushEnter: Transition { - XAnimator { - duration: AssistantStyle.stackAnimation.duration - easing.type: Easing.OutBack - from: stack.width + AssistantStyle.rightMargin - to: 0 - } - } - - pushExit: Transition { - YAnimator { - duration: AssistantStyle.stackAnimation.duration - easing.type: Easing.OutBack - from: 0 - to: stack.height + AssistantStyle.bottomMargin - } - } - } + id: assistant + // --------------------------------------------------------------------------- + + Rectangle { + anchors.fill: parent + color: AssistantStyle.color + } + function pushView (view, properties) { + stack.pushView(view, properties) + } + + function getView (index) { + return stack.getView(index) + } + + function popView () { + stack.popView() + } + // --------------------------------------------------------------------------- + + StackView { + id: stack + anchors.fill: parent + + viewsPath: 'qrc:/ui/views/App/Main/Assistant/' + initialItem: viewsPath + 'AssistantHome.qml' + + onExit:window.setView('Home') + } } diff --git a/linphone-app/ui/views/App/Main/Conferences.qml b/linphone-app/ui/views/App/Main/Conferences.qml index 7616ed0fd..58b2303d3 100644 --- a/linphone-app/ui/views/App/Main/Conferences.qml +++ b/linphone-app/ui/views/App/Main/Conferences.qml @@ -58,11 +58,18 @@ ColumnLayout { texts: [ 'TERMINEES', 'PROGRAMMEES', - 'INVITATIONS' + 'INVITATIONS', + 'TEST' ] selectedButton: mainItem.filterType onClicked: { - mainItem.filterType = (button === 0 ? ConferenceInfoProxyModel.Ended : button === 1 ?ConferenceInfoProxyModel.Scheduled : ConferenceInfoProxyModel.Invitations); + if(button <= 2) + mainItem.filterType = (button === 0 ? ConferenceInfoProxyModel.Ended : button === 1 ?ConferenceInfoProxyModel.Scheduled : ConferenceInfoProxyModel.Invitations); + else { + window.detachVirtualWindow() + window.attachVirtualWindow(Qt.resolvedUrl('../Calls/VideoConferenceMenu.qml')) + } + //mainItem.filterType = button } } diff --git a/linphone-app/ui/views/App/Styles/Calls/VideoConferenceMenuStyle.qml b/linphone-app/ui/views/App/Styles/Calls/VideoConferenceMenuStyle.qml new file mode 100644 index 000000000..56ca9c81c --- /dev/null +++ b/linphone-app/ui/views/App/Styles/Calls/VideoConferenceMenuStyle.qml @@ -0,0 +1,87 @@ +pragma Singleton +import QtQml 2.2 +import QtQuick 2.7 + +import Units 1.0 +import ColorsList 1.0 + +// ============================================================================= + +QtObject { + property string sectionName: 'VideoConferenceMenu' + property color backgroundColor: ColorsList.add(sectionName+'_bg', 'k').color + property int radius: 8 + property QtObject header: QtObject{ + property string name: 'header' + property int height: 60 + property color color: ColorsList.add(sectionName+'_'+name+'_fg', 'j').color + property int weight: Font.Bold + property int pointSize: Units.dp * 14 + } + property QtObject list : QtObject{ + property string name: 'list' + property int height: 60 + property color color: ColorsList.add(sectionName+'_'+name+'_fg', 'j').color + property int weight: Font.Normal + property int selectedWeight: Font.Bold + property int pointSize: Units.dp * 12 + + property QtObject border: QtObject{ + property color color: ColorsList.add(sectionName+'_list_border', 'f').color + property int width: 2 + } + } + + property QtObject modeIcons: QtObject{ + property string gridIcon: 'conference_layout_grid' + property string activeSpeakerIcon: 'conference_layout_active_speaker' + property int width: 80 + property int height: 50 + } + property QtObject settingsIcons: QtObject{ + property string gridIcon: 'conference_layout_grid_custom' + property string activeSpeakerIcon: 'conference_layout_active_speaker' + property int width: 50 + property int height: 50 + } + + //------------------------------------------------------------------------------ + property QtObject buttons: QtObject{ + property QtObject close: QtObject { + property int iconSize: 40 + property string icon : 'close_custom' + property string name : 'close' + property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_h_b_bg').color + property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_n_b_bg').color + property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg').color + property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_h_b_fg').color + property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg').color + property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color + } + property QtObject back: QtObject { + property int iconSize: 40 + property string icon : 'back_custom' + property string name : 'back' + property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_h_b_bg').color + property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_n_b_bg').color + property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg').color + property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_h_b_fg').color + property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg').color + property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color + } + property QtObject next: QtObject { + property int iconSize: 40 + property string icon : 'panel_arrow_custom' + property string name : 'next' + property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_h_b_bg').color + property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_n_b_bg').color + property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_bg').color + property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_h_b_fg').color + property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_n_b_fg').color + property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color + } + + } + //------------------------------------------------------------------------------ + +} diff --git a/linphone-app/ui/views/App/Styles/qmldir b/linphone-app/ui/views/App/Styles/qmldir index 0862d1391..6f9a447b5 100644 --- a/linphone-app/ui/views/App/Styles/qmldir +++ b/linphone-app/ui/views/App/Styles/qmldir @@ -12,6 +12,7 @@ singleton CallsWindowStyle 1.0 Calls/CallsWindowSt singleton WaitingRoomStyle 1.0 Calls/WaitingRoomStyle.qml singleton ConferenceStyle 1.0 Calls/ConferenceStyle.qml singleton VideoConferenceStyle 1.0 Calls/VideoConferenceStyle.qml +singleton VideoConferenceMenuStyle 1.0 Calls/VideoConferenceMenuStyle.qml singleton CallSipAddressStyle 1.0 Calls/Dialogs/CallSipAddressStyle.qml singleton CallTransferStyle 1.0 Calls/Dialogs/CallTransferStyle.qml diff --git a/linphone-sdk b/linphone-sdk index dbc1ed98c..45009739f 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit dbc1ed98c46a241a4548c42eccad09332907f4be +Subproject commit 45009739fe36bba8f70647e526d354cbcf8c06a4