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