Ui fixes, add participants panel, admin status, conf edition

This commit is contained in:
Gaelle Braud 2024-03-29 11:18:19 +01:00 committed by Julien Wadel
parent 576bd0892c
commit 3b64a8c4ae
25 changed files with 654 additions and 612 deletions

View file

@ -38,6 +38,11 @@ ConferenceCore::ConferenceCore(const std::shared_ptr<linphone::Conference> &conf
mustBeInLinphoneThread(getClassName());
mConferenceModel = ConferenceModel::create(conference);
mSubject = Utils::coreStringToAppString(conference->getSubject());
mParticipantDeviceCount = conference->getParticipantDeviceList().size();
auto me = conference->getMe();
if (me) {
mMe = ParticipantCore::create(me);
}
}
ConferenceCore::~ConferenceCore() {
mustBeInMainThread("~" + getClassName());
@ -77,7 +82,7 @@ Q_INVOKABLE qint64 ConferenceCore::getElapsedSeconds() const {
// std::list<std::shared_ptr<linphone::Participant>>
// getParticipantList() const; // SDK exclude me. We want to get ALL participants.
int ConferenceCore::getParticipantDeviceCount() const {
return 0;
return mParticipantDeviceCount + 1;
}
void ConferenceCore::setIsReady(bool state) {
@ -100,6 +105,10 @@ ParticipantDeviceGui *ConferenceCore::getActiveSpeakerGui() const {
return new ParticipantDeviceGui(mActiveSpeaker);
}
ParticipantGui *ConferenceCore::getMeGui() const {
return new ParticipantGui(mMe);
}
void ConferenceCore::setActiveSpeaker(const QSharedPointer<ParticipantDeviceCore> &device) {
if (mActiveSpeaker != device) {
mActiveSpeaker = device;

View file

@ -21,8 +21,10 @@
#ifndef CONFERENCE_CORE_H_
#define CONFERENCE_CORE_H_
#include "core/participant/ParticipantCore.hpp"
#include "core/participant/ParticipantDeviceCore.hpp"
#include "core/participant/ParticipantDeviceGui.hpp"
#include "core/participant/ParticipantGui.hpp"
#include "model/conference/ConferenceModel.hpp"
#include "tool/LinphoneEnums.hpp"
#include "tool/thread/SafeConnection.hpp"
@ -36,11 +38,12 @@ class ConferenceCore : public QObject, public AbstractObject {
public:
Q_PROPERTY(QString subject READ getSubject NOTIFY subjectChanged)
Q_PROPERTY(QDateTime startDate READ getStartDate CONSTANT)
// Q_PROPERTY(ParticipantListModel* participants READ getParticipantListModel CONSTANT)
// Q_PROPERTY(ParticipantDeviceList *participantDevices READ getParticipantDeviceList CONSTANT)
// Q_PROPERTY(ParticipantModel* localParticipant READ getLocalParticipant NOTIFY localParticipantChanged)
Q_PROPERTY(bool isReady MEMBER mIsReady WRITE setIsReady NOTIFY isReadyChanged)
Q_PROPERTY(int participantDeviceCount READ getParticipantDeviceCount NOTIFY participantDeviceCountChanged)
Q_PROPERTY(ParticipantDeviceGui *activeSpeaker READ getActiveSpeakerGui NOTIFY activeSpeakerChanged)
Q_PROPERTY(ParticipantGui *me READ getMeGui)
// Should be call from model Thread. Will be automatically in App thread after initialization
static QSharedPointer<ConferenceCore> create(const std::shared_ptr<linphone::Conference> &conference);
@ -57,9 +60,11 @@ public:
// ParticipantListModel *getParticipantListModel() const;
// std::list<std::shared_ptr<linphone::Participant>>
// getParticipantList() const; // SDK exclude me. We want to get ALL participants.
// void getParticipantDeviceList() const;
int getParticipantDeviceCount() const;
ParticipantDeviceCore *getActiveSpeaker() const;
ParticipantDeviceGui *getActiveSpeakerGui() const;
ParticipantGui *getMeGui() const;
void setActiveSpeaker(const QSharedPointer<ParticipantDeviceCore> &device);
void setIsReady(bool state);
@ -78,6 +83,8 @@ private:
QSharedPointer<SafeConnection<ConferenceCore, ConferenceModel>> mConferenceModelConnection;
std::shared_ptr<ConferenceModel> mConferenceModel;
QSharedPointer<ParticipantDeviceCore> mActiveSpeaker;
QSharedPointer<ParticipantCore> mMe;
int mParticipantDeviceCount = 0;
bool mIsReady = false;
QString mSubject;

View file

@ -120,7 +120,7 @@ ConferenceInfoList::get(std::shared_ptr<linphone::ConferenceInfo> conferenceInfo
QSharedPointer<ConferenceInfoCore>
ConferenceInfoList::build(const std::shared_ptr<linphone::ConferenceInfo> &conferenceInfo) const {
auto me = CoreModel::getInstance()->getCore()->getDefaultAccount()->getParams()->getIdentityAddress();
qDebug() << "[CONFERENCEINFOLIST] looking for me " << me->asStringUriOnly();
// qDebug() << "[CONFERENCEINFOLIST] looking for me " << me->asStringUriOnly();
std::list<std::shared_ptr<linphone::ParticipantInfo>> participants = conferenceInfo->getParticipantInfos();
bool haveMe = conferenceInfo->getOrganizer()->weakEqual(me);
if (!haveMe)

View file

@ -41,18 +41,21 @@ QSharedPointer<ParticipantCore> ParticipantCore::create(const std::shared_ptr<li
ParticipantCore::ParticipantCore(const std::shared_ptr<linphone::Participant> &participant) : QObject(nullptr) {
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
mParticipantModel = Utils::makeQObject_ptr<ParticipantModel>(participant);
mAdminStatus = participant->isAdmin();
mSipAddress = Utils::coreStringToAppString(participant->getAddress()->asStringUriOnly());
mCreationTime = QDateTime::fromSecsSinceEpoch(participant->getCreationTime());
mDisplayName = Utils::coreStringToAppString(participant->getAddress()->getDisplayName());
if (mDisplayName.isEmpty()) mDisplayName = Utils::coreStringToAppString(participant->getAddress()->getUsername());
for (auto &device : participant->getDevices()) {
auto name = Utils::coreStringToAppString(device->getName());
auto address = Utils::coreStringToAppString(device->getAddress()->asStringUriOnly());
QVariantMap map;
map.insert("name", name);
map.insert("address", address);
mParticipantDevices.append(map);
if (participant) {
mAdminStatus = participant->isAdmin();
mSipAddress = Utils::coreStringToAppString(participant->getAddress()->asStringUriOnly());
mCreationTime = QDateTime::fromSecsSinceEpoch(participant->getCreationTime());
mDisplayName = Utils::coreStringToAppString(participant->getAddress()->getDisplayName());
if (mDisplayName.isEmpty())
mDisplayName = Utils::coreStringToAppString(participant->getAddress()->getUsername());
for (auto &device : participant->getDevices()) {
auto name = Utils::coreStringToAppString(device->getName());
auto address = Utils::coreStringToAppString(device->getAddress()->asStringUriOnly());
QVariantMap map;
map.insert("name", name);
map.insert("address", address);
mParticipantDevices.append(map);
}
}
// App::getInstance()->mEngine->setObjectOwnership(mParticipantDevices.get(),
// QQmlEngine::CppOwnership); // Managed by QSharedPointer

View file

@ -95,7 +95,7 @@ signals:
void creationTimeChanged();
void displayNameChanged();
void lStartInvitation(const int &secs);
void lStartInvitation(const int &secs = 30);
void lSetIsAdmin(bool status);
void invitationTimeout(ParticipantCore *model);

View file

@ -245,6 +245,45 @@ void ParticipantList::remove(ParticipantCore *participant) {
}
}
void ParticipantList::addAddress(const QString &address) {
if (!contains(address)) {
QSharedPointer<ParticipantCore> participant = QSharedPointer<ParticipantCore>::create(nullptr);
connect(participant.get(), &ParticipantCore::invitationTimeout, this, &ParticipantList::remove);
participant->setSipAddress(address);
add(participant);
// if (mChatRoomModel && mChatRoomModel->getChatRoom()) { // Invite and wait for its creation
// participant->startInvitation();
// mChatRoomModel->getChatRoom()->addParticipant(Utils::interpretUrl(address));
// }
if (mConferenceModel) {
std::list<std::shared_ptr<linphone::Call>> runningCallsToAdd;
mConferenceModelConnection->invokeToModel([this, address] {
auto addressToInvite = ToolModel::interpretUrl(address);
auto currentCalls = CoreModel::getInstance()->getCore()->getCalls();
auto haveCall = std::find_if(currentCalls.begin(), currentCalls.end(),
[addressToInvite](const std::shared_ptr<linphone::Call> &call) {
return call->getRemoteAddress()->weakEqual(addressToInvite);
});
if (haveCall == currentCalls.end()) mConferenceModel->addParticipant(addressToInvite);
});
// else {
// runningCallsToAdd.push_back(*haveCall);
// mConferenceModel->addParticipants(runningCallsToAdd);
// }
/*
std::list<std::shared_ptr<linphone::Address>> addressesToInvite;
addressesToInvite.push_back(addressToInvite);
auto callParameters =
CoreManager::getInstance()->getCore()->createCallParams(mConferenceModel->getConference()->getCall());
mConferenceModel->getConference()->inviteParticipants(addressesToInvite, callParameters);*/
}
emit participant->lStartInvitation();
emit countChanged();
// emit addressAdded(address);
}
}
// const QSharedPointer<ParticipantCore>
// ParticipantList::getParticipant(const std::shared_ptr<const linphone::Address> &address) const {
// if (address) {
@ -271,7 +310,8 @@ void ParticipantList::remove(ParticipantCore *participant) {
//-------------------------------------------------------------
// void ParticipantList::setAdminStatus(const std::shared_ptr<linphone::Participant> participant, const bool &isAdmin) {
// void ParticipantList::setAdminStatus(const std::shared_ptr<linphone::Participant> participant, const bool
// &isAdmin) {
// // if (mChatRoomModel) mChatRoomModel->getChatRoom()->setParticipantAdminStatus(participant, isAdmin);
// // if (mConferenceModel) mConferenceModel->getConference()->setParticipantAdminStatus(participant, isAdmin);
// }
@ -324,8 +364,8 @@ void ParticipantList::remove(ParticipantCore *participant) {
// // if (participant) remove(participant.get());
// }
// void ParticipantList::onParticipantAdminStatusChanged(const std::shared_ptr<const linphone::EventLog> &eventLog) {
// onParticipantAdminStatusChanged(eventLog->getParticipantAddress());
// void ParticipantList::onParticipantAdminStatusChanged(const std::shared_ptr<const linphone::EventLog> &eventLog)
// { onParticipantAdminStatusChanged(eventLog->getParticipantAddress());
// }
// void ParticipantList::onParticipantAdminStatusChanged(const std::shared_ptr<const linphone::Participant>
// &participant) {

View file

@ -51,6 +51,8 @@ public:
// getParticipant(const std::shared_ptr<const linphone::Participant> &participant) const;
Q_INVOKABLE void remove(ParticipantCore *participant);
void addAddress(const QString &address);
std::list<std::shared_ptr<linphone::Address>> getParticipants() const;
bool contains(const QString &address) const;
@ -77,8 +79,8 @@ public:
// void onParticipantDeviceRemoved(const std::shared_ptr<const linphone::EventLog> &eventLog);
// void
// onParticipantRegistrationSubscriptionRequested(const std::shared_ptr<const linphone::Address>
// &participantAddress); void onParticipantRegistrationUnsubscriptionRequested( const std::shared_ptr<const
// linphone::Address> &participantAddress); void onStateChanged();
// &participantAddress); void onParticipantRegistrationUnsubscriptionRequested( const
// std::shared_ptr<const linphone::Address> &participantAddress); void onStateChanged();
signals:
void securityLevelChanged();

View file

@ -152,41 +152,14 @@ void ParticipantProxy::setShowMe(const bool &show) {
}
}
// void ParticipantProxy::addAddress(const QString &address) {
// if (!participantsModel->contains(address)) {
// QSharedPointer<ParticipantCore> participant = QSharedPointer<ParticipantCore>::create(nullptr);
// connect(participant.get(), &ParticipantCore::invitationTimeout, this, &ParticipantProxy::removeModel);
// participant->setSipAddress(address);
// participantsModel->add(participant);
// if (mChatRoomModel && mChatRoomModel->getChatRoom()) { // Invite and wait for its creation
// participant->startInvitation();
// mChatRoomModel->getChatRoom()->addParticipant(Utils::interpretUrl(address));
// }
// if (mConferenceModel && mConferenceModel->getConference()) {
// auto addressToInvite = Utils::interpretUrl(address);
// std::list<std::shared_ptr<linphone::Call>> runningCallsToAdd;
// auto currentCalls = CoreManager::getInstance()->getCore()->getCalls();
// auto haveCall = std::find_if(currentCalls.begin(), currentCalls.end(),
// [addressToInvite](const std::shared_ptr<linphone::Call> &call) {
// return call->getRemoteAddress()->weakEqual(addressToInvite);
// });
// participant->startInvitation();
// if (haveCall == currentCalls.end()) mConferenceModel->getConference()->addParticipant(addressToInvite);
// else {
// runningCallsToAdd.push_back(*haveCall);
// mConferenceModel->getConference()->addParticipants(runningCallsToAdd);
// }
// /*
// std::list<std::shared_ptr<linphone::Address>> addressesToInvite;
// addressesToInvite.push_back(addressToInvite);
// auto callParameters =
// CoreManager::getInstance()->getCore()->createCallParams(mConferenceModel->getConference()->getCall());
// mConferenceModel->getConference()->inviteParticipants(addressesToInvite, callParameters);*/
// }
// emit countChanged();
// emit addressAdded(address);
// }
// }
void ParticipantProxy::addAddress(const QString &address) {
mParticipants->addAddress(address);
}
void ParticipantProxy::addAddresses(const QStringList &addresses) {
for (auto &address : addresses)
mParticipants->addAddress(address);
}
void ParticipantProxy::removeParticipant(ParticipantCore *participant) {
if (participant) {

View file

@ -60,7 +60,8 @@ public:
void setConferenceModel(ConferenceModel *conferenceModel);
void setShowMe(const bool &show);
// Q_INVOKABLE void addAddress(const QString &address);
Q_INVOKABLE void addAddress(const QString &address);
Q_INVOKABLE void addAddresses(const QStringList &addresses);
Q_INVOKABLE void removeParticipant(ParticipantCore *participant);
Q_INVOKABLE void setParticipantAdminStatus(ParticipantCore *participant, bool status);
Q_INVOKABLE void setAddresses(ConferenceInfoModel *conferenceInfoModel);

View file

@ -52,11 +52,11 @@ void ConferenceModel::setPaused(bool paused) {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
}
void ConferenceModel::removeParticipant(std::shared_ptr<linphone::Participant> p) {
void ConferenceModel::removeParticipant(const std::shared_ptr<linphone::Participant> &p) {
mMonitor->removeParticipant(p);
}
void ConferenceModel::removeParticipant(std::shared_ptr<linphone::Address> address) {
void ConferenceModel::removeParticipant(const std::shared_ptr<linphone::Address> &address) {
for (auto &p : mMonitor->getParticipantList()) {
if (address->asStringUriOnly() == p->getAddress()->asStringUriOnly()) {
mMonitor->removeParticipant(p);
@ -64,6 +64,10 @@ void ConferenceModel::removeParticipant(std::shared_ptr<linphone::Address> addre
}
}
void ConferenceModel::addParticipant(const std::shared_ptr<linphone::Address> &address) {
mMonitor->addParticipant(address);
}
void ConferenceModel::setMicrophoneMuted(bool isMuted) {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
mMonitor->setMicrophoneMuted(isMuted);

View file

@ -51,8 +51,9 @@ public:
void setPaused(bool paused);
void removeParticipant(std::shared_ptr<linphone::Participant> p);
void removeParticipant(std::shared_ptr<linphone::Address> address);
void removeParticipant(const std::shared_ptr<linphone::Participant> &p);
void removeParticipant(const std::shared_ptr<linphone::Address> &address);
void addParticipant(const std::shared_ptr<linphone::Address> &address);
signals:
void microphoneMutedChanged(bool isMuted);

View file

@ -29,7 +29,6 @@ DEFINE_ABSTRACT_OBJECT(ParticipantModel)
ParticipantModel::ParticipantModel(std::shared_ptr<linphone::Participant> linphoneParticipant, QObject *parent)
: QObject(parent) {
mParticipant = linphoneParticipant;
assert(mParticipant);
}
ParticipantModel::~ParticipantModel() {

View file

@ -32,11 +32,17 @@ Window {
property var callObj
function joinConference(withVideo) {
if (!conferenceInfo || conferenceInfo.core.uri.length === 0) UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("La conférence n'a pas pu démarrer en raison d'une erreur d'uri."))
if (!conferenceInfo || conferenceInfo.core.uri.length === 0) UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("La conférence n'a pas pu démarrer en raison d'une erreur d'uri."), mainWindow)
else {
callObj = UtilsCpp.createCall(conferenceInfo.core.uri, withVideo)
}
}
function showInformationPopup(title, description, isSuccess) {
var infoPopup = popupComp.createObject(popupLayout, {"title": title, "description": description, "isSuccess": isSuccess})
infoPopup.index = popupLayout.popupList.length
popupLayout.popupList.push(infoPopup)
infoPopup.open()
}
Connections {
enabled: call != undefined && call != null
@ -372,238 +378,271 @@ Window {
Layout.rightMargin: 10 * DefaultStyle.dp
visible: false
function replace(id) {
rightPanelStack.replace(id, Control.StackView.Immediate)
contentStackView.replace(id, Control.StackView.Immediate)
}
headerContent: Text {
id: rightPanelTitle
anchors.verticalCenter: parent.verticalCenter
width: rightPanel.width
color: mainWindow.conference ? DefaultStyle.main1_500_main : DefaultStyle.main2_700
// text: qsTr("Transfert d'appel")
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
headerStack.currentIndex: 0
contentStackView.initialItem: callsListPanel
headerValidateButtonText: qsTr("Ajouter")
}
Component {
id: contactsListPanel
CallContactsLists {
Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Transfert d'appel")
sideMargin: 10 * DefaultStyle.dp
topMargin: 15 * DefaultStyle.dp
groupCallVisible: false
searchBarColor: DefaultStyle.grey_0
searchBarBorderColor: DefaultStyle.grey_200
onCallButtonPressed: (address) => {
mainWindow.call.core.lTransferCall(address)
}
}
Control.StackView {
id: rightPanelStack
width: parent.width
height: parent.height
initialItem: callsListPanel
Component {
id: contactsListPanel
CallContactsLists {
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Transfert d'appel")
sideMargin: 10 * DefaultStyle.dp
topMargin: 15 * DefaultStyle.dp
groupCallVisible: false
searchBarColor: DefaultStyle.grey_0
searchBarBorderColor: DefaultStyle.grey_200
onCallButtonPressed: (address) => {
mainWindow.call.core.lTransferCall(address)
}
}
}
Component {
id: dialerPanel
ColumnLayout {
Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Dialer")
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
Component {
id: dialerPanel
ColumnLayout {
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Dialer")
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
SearchBar {
id: dialerTextInput
Layout.fillWidth: true
Layout.leftMargin: 10 * DefaultStyle.dp
Layout.rightMargin: 10 * DefaultStyle.dp
magnifierVisible: false
color: DefaultStyle.grey_0
borderColor: DefaultStyle.grey_200
placeholderText: ""
numericPad: numPad
numericPadButton.visible: false
}
Item {
Layout.fillWidth: true
Layout.preferredHeight: numPad.height
Layout.topMargin: 10 * DefaultStyle.dp
property var callObj
NumericPad {
id: numPad
width: parent.width
visible: parent.visible
closeButtonVisible: false
onLaunchCall: {
callObj = UtilsCpp.createCall(dialerTextInput.text + "@sip.linphone.org")
}
}
}
}
SearchBar {
id: dialerTextInput
Layout.fillWidth: true
Layout.leftMargin: 10 * DefaultStyle.dp
Layout.rightMargin: 10 * DefaultStyle.dp
magnifierVisible: false
color: DefaultStyle.grey_0
borderColor: DefaultStyle.grey_200
placeholderText: ""
numericPad: numPad
numericPadButton.visible: false
}
Component {
id: callsListPanel
ColumnLayout {
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Liste d'appel")
RoundedBackgroundControl {
Layout.fillWidth: true
// height: Math.min(callList.height + topPadding + bottomPadding, rightPanelStack.height)
Layout.preferredHeight: Math.min(callList.height + topPadding + bottomPadding, rightPanelStack.height)
topPadding: 15 * DefaultStyle.dp
bottomPadding: 15 * DefaultStyle.dp
leftPadding: 15 * DefaultStyle.dp
rightPadding: 15 * DefaultStyle.dp
backgroundColor: DefaultStyle.main2_0
contentItem: ListView {
id: callList
model: callsModel
height: Math.min(contentHeight, rightPanelStack.height)
spacing: 15 * DefaultStyle.dp
onCountChanged: forceLayout()
delegate: Item {
id: callDelegate
width: callList.width
height: 45 * DefaultStyle.dp
RowLayout {
id: delegateContent
anchors.fill: parent
anchors.leftMargin: 10 * DefaultStyle.dp
anchors.rightMargin: 10 * DefaultStyle.dp
Avatar {
id: delegateAvatar
address: modelData.core.peerAddress
Layout.preferredWidth: 45 * DefaultStyle.dp
Layout.preferredHeight: 45 * DefaultStyle.dp
}
Text {
id: delegateName
property var remoteAddress: UtilsCpp.getDisplayName(modelData.core.peerAddress)
text: remoteAddress ? remoteAddress.value : ""
Connections {
target: modelData.core
}
}
Item {
Layout.fillHeight: true
Layout.fillWidth: true
}
Text {
id: callStateText
text: modelData.core.state === LinphoneEnums.CallState.Paused
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
? qsTr("Appel en pause") : qsTr("Appel en cours")
}
PopupButton {
id: listCallOptionsButton
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
Layout.alignment: Qt.AlignRight
popup.contentItem: ColumnLayout {
spacing: 0
Control.Button {
background: Item {}
contentItem: RowLayout {
Image {
source: modelData.core.state === LinphoneEnums.CallState.Paused
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
? AppIcons.phone : AppIcons.pause
sourceSize.width: 32 * DefaultStyle.dp
sourceSize.height: 32 * DefaultStyle.dp
Layout.preferredWidth: 32 * DefaultStyle.dp
Layout.preferredHeight: 32 * DefaultStyle.dp
fillMode: Image.PreserveAspectFit
}
Text {
text: modelData.core.state === LinphoneEnums.CallState.Paused
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
? qsTr("Reprendre l'appel") : qsTr("Mettre en pause")
color: DefaultStyle.main2_500main
Layout.preferredWidth: metrics.width
}
TextMetrics {
id: metrics
text: qsTr("Reprendre l'appel")
}
Item {
Layout.fillWidth: true
}
}
onClicked: modelData.core.lSetPaused(!modelData.core.paused)
}
Control.Button {
background: Item {}
contentItem: RowLayout {
EffectImage {
imageSource: AppIcons.endCall
colorizationColor: DefaultStyle.danger_500main
width: 32 * DefaultStyle.dp
height: 32 * DefaultStyle.dp
}
Text {
color: DefaultStyle.danger_500main
text: qsTr("Terminer l'appel")
}
Item {
Layout.fillWidth: true
}
}
onClicked: mainWindow.endCall(modelData)
}
}
}
}
// MouseArea{
// anchors.fill: delegateLayout
// onClicked: {
// callsModel.currentCall = modelData
// }
// }
}
}
}
Item {
Layout.fillHeight: true
}
}
}
Component {
id: settingsPanel
InCallSettingsPanel {
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Paramètres")
call: mainWindow.call
}
}
Component {
id: participantListPanel
StackLayout {
id: participantsStack
currentIndex: 0
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Participants (%1)").arg(count)
onCurrentIndexChanged: {
if (index === 0) rightPanelTitle.text = qsTr("Participants (%1)").arg(count)
else rightPanelTitle.text = qsTr("Ajouter des participants")
}
ParticipantList {
call: mainWindow.call
onCountChanged: if (Control.StackView.status === Control.StackView.Active) {
rightPanelTitle.text = qsTr("Participants (%1)").arg(count)
}
onAddParticipantRequested: participantsStack.currentIndex = 1
}
AddParticipantsLayout {
conferenceInfoGui: mainWindow.conferenceInfo
Item {
Layout.fillWidth: true
Layout.preferredHeight: numPad.height
Layout.topMargin: 10 * DefaultStyle.dp
property var callObj
NumericPad {
id: numPad
width: parent.width
visible: parent.visible
closeButtonVisible: false
onLaunchCall: {
callObj = UtilsCpp.createCall(dialerTextInput.text + "@sip.linphone.org")
}
}
}
}
}
Component {
id: callsListPanel
ColumnLayout {
Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Liste d'appel")
RoundedBackgroundControl {
Layout.fillWidth: true
Layout.preferredHeight: Math.min(callList.implicitHeight + topPadding + bottomPadding, rightPanel.height)
topPadding: 15 * DefaultStyle.dp
bottomPadding: 15 * DefaultStyle.dp
leftPadding: 15 * DefaultStyle.dp
rightPadding: 15 * DefaultStyle.dp
backgroundColor: mainWindow.conference ? DefaultStyle.grey_0 : DefaultStyle.main2_0
contentItem: ListView {
id: callList
model: callsModel
implicitHeight: contentHeight// Math.min(contentHeight, rightPanel.height)
spacing: 15 * DefaultStyle.dp
clip: true
onCountChanged: forceLayout()
delegate: Item {
id: callDelegate
width: callList.width
height: 45 * DefaultStyle.dp
RowLayout {
id: delegateContent
anchors.fill: parent
anchors.leftMargin: 10 * DefaultStyle.dp
anchors.rightMargin: 10 * DefaultStyle.dp
Avatar {
id: delegateAvatar
address: modelData.core.peerAddress
Layout.preferredWidth: 45 * DefaultStyle.dp
Layout.preferredHeight: 45 * DefaultStyle.dp
}
Text {
id: delegateName
property var remoteAddress: UtilsCpp.getDisplayName(modelData.core.peerAddress)
text: remoteAddress ? remoteAddress.value : ""
Connections {
target: modelData.core
}
}
Item {
Layout.fillHeight: true
Layout.fillWidth: true
}
Text {
id: callStateText
text: modelData.core.state === LinphoneEnums.CallState.Paused
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
? qsTr("Appel en pause") : qsTr("Appel en cours")
}
PopupButton {
id: listCallOptionsButton
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
Layout.alignment: Qt.AlignRight
popup.contentItem: ColumnLayout {
spacing: 0
Control.Button {
background: Item {}
contentItem: RowLayout {
Image {
source: modelData.core.state === LinphoneEnums.CallState.Paused
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
? AppIcons.phone : AppIcons.pause
sourceSize.width: 32 * DefaultStyle.dp
sourceSize.height: 32 * DefaultStyle.dp
Layout.preferredWidth: 32 * DefaultStyle.dp
Layout.preferredHeight: 32 * DefaultStyle.dp
fillMode: Image.PreserveAspectFit
}
Text {
text: modelData.core.state === LinphoneEnums.CallState.Paused
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
? qsTr("Reprendre l'appel") : qsTr("Mettre en pause")
color: DefaultStyle.main2_500main
Layout.preferredWidth: metrics.width
}
TextMetrics {
id: metrics
text: qsTr("Reprendre l'appel")
}
Item {
Layout.fillWidth: true
}
}
onClicked: modelData.core.lSetPaused(!modelData.core.paused)
}
Control.Button {
background: Item {}
contentItem: RowLayout {
EffectImage {
imageSource: AppIcons.endCall
colorizationColor: DefaultStyle.danger_500main
width: 32 * DefaultStyle.dp
height: 32 * DefaultStyle.dp
}
Text {
color: DefaultStyle.danger_500main
text: qsTr("Terminer l'appel")
}
Item {
Layout.fillWidth: true
}
}
onClicked: mainWindow.endCall(modelData)
}
}
}
}
// MouseArea{
// anchors.fill: delegateLayout
// onClicked: {
// callsModel.currentCall = modelData
// }
// }
}
}
}
Item {
Layout.fillHeight: true
}
}
}
Component {
id: settingsPanel
InCallSettingsPanel {
Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Paramètres")
call: mainWindow.call
}
}
Component {
id: participantListPanel
Control.StackView {
id: participantsStack
initialItem: participantListComp
// Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Participants (%1)").arg(participantList.count)
onCurrentItemChanged: rightPanel.headerStack.currentIndex = currentItem.Control.StackView.index
property list<string> selectedParticipants
signal participantAdded()
Connections {
target: rightPanel
onReturnRequested: participantsStack.pop()
}
Component {
id: participantListComp
ParticipantList {
id: participantList
call: mainWindow.call
onAddParticipantRequested: participantsStack.push(addParticipantComp)
onCountChanged: if (participantsStack.Control.StackView.status === Control.StackView.Active && participantsStack.currentItem == participantList) {
rightPanel.headerTitleText = qsTr("Participants (%1)").arg(count)
}
Connections {
target: participantsStack
onCurrentItemChanged: {
console.log("changing title", participantsStack.currentItem == participantList)
if (participantsStack.currentItem == participantList) rightPanel.headerTitleText = qsTr("Participants (%1)").arg(participantList.count)
}
}
Connections {
target: rightPanel
// TODO : chercher comment relier ces infos pour faire le add des participants
onValidateRequested: {
participantList.model.addAddresses(participantsStack.selectedParticipants)
participantsStack.pop()
participantsStack.participantAdded()
}
}
}
}
Component {
id: addParticipantComp
AddParticipantsLayout {
id: addParticipantLayout
titleLayout.visible: false
onSelectedParticipantsCountChanged: {
if (participantsStack.Control.StackView.status === Control.StackView.Active && Control.StackView.visible) {
rightPanel.headerSubtitleText = qsTr("%1 participant%2 sélectionné").arg(selectedParticipants.length).arg(selectedParticipants.length > 1 ? "s" : "")
}
participantsStack.selectedParticipants = selectedParticipants
}
Connections {
target: participantsStack
onCurrentItemChanged: {
if (participantsStack.currentItem == addParticipantLayout) {
rightPanel.headerTitleText = qsTr("Ajouter des participants")
rightPanel.headerSubtitleText = qsTr("%1 participant%2 sélectionné").arg(addParticipantLayout.selectedParticipants.length).arg(addParticipantLayout.selectedParticipants.length > 1 ? "s" : "")
}
}
onParticipantAdded: {
addParticipantLayout.clearSelectedParticipants()
}
}
}
}
}
}
}
Component {
id: waitingRoom
@ -805,6 +844,7 @@ Window {
onCheckedChanged: mainWindow.call.core.lSetMicrophoneMuted(!mainWindow.call.core.microphoneMuted)
}
CheckableButton {
visible: mainWindow.conference
iconUrl: AppIcons.usersTwo
checked: mainWindow.call && mainWindow.call.core.microphoneMuted
checkedColor: DefaultStyle.main2_400
@ -830,7 +870,7 @@ Window {
icon.source: AppIcons.more
background: Rectangle {
anchors.fill: moreOptionsButton
color: moreOptionsButton.enabled
color: moreOptionsButton.enabled
? moreOptionsButton.checked
? DefaultStyle.grey_0
: DefaultStyle.grey_500
@ -838,7 +878,13 @@ Window {
radius: 40 * DefaultStyle.dp
}
popup.x: width/2
popup.y: y - popup.height + height/4
Connections {
target: moreOptionsButton.popup
onOpened: {
console.log("y", moreOptionsButton.y, moreOptionsButton.popup.y, moreOptionsButton.popup.height)
moreOptionsButton.popup.y = - moreOptionsButton.popup.height + moreOptionsButton.height/4
}
}
popup.contentItem: ColumnLayout {
id: optionsList
spacing: 10 * DefaultStyle.dp

View file

@ -178,7 +178,7 @@ Item {
rightMargin: 15 * DefaultStyle.dp
initialHeadersVisible: false
contactMenuVisible: false
actionMenuVisible: true
actionLayoutVisible: true
model: MagicSearchProxy {
searchText: magicSearchBar.text.length === 0 ? "*" : magicSearchBar.text
aggregationFlag: LinphoneEnums.MagicSearchAggregation.Friend

View file

@ -65,14 +65,13 @@ Control.Button {
}
component ButtonText: Text {
visible: mainItem.text != undefined
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
width: mainItem.text != undefined ? implicitWidth : 0
height: implicitHeight
wrapMode: Text.WrapAnywhere
Layout.fillWidth: true
Layout.fillHeight: true
// Layout.fillWidth: true
// Layout.fillHeight: true
text: mainItem.text
maximumLineCount: 1
color: inversedColors ? mainItem.color : mainItem.textColor
@ -86,9 +85,8 @@ Control.Button {
}
component ButtonImage: EffectImage {
visible: mainItem.icon.source != undefined
Layout.fillWidth: true
Layout.fillHeight: true
// Layout.fillWidth: true
// Layout.fillHeight: true
imageSource: mainItem.icon.source
imageWidth: mainItem.icon.width
imageHeight: mainItem.icon.height
@ -96,11 +94,12 @@ Control.Button {
}
contentItem: StackLayout {
currentIndex: mainItem.text.length != 0 && mainItem.icon.source != undefined
id: stacklayout
currentIndex: mainItem.text.length != 0 && mainItem.icon.source.toString().length != 0
? 0
: mainItem.text.length != 0
? 1
: mainItem.icon.source != undefined
: mainItem.icon.source.toString().length != 0
? 2
: 3

View file

@ -1,4 +1,4 @@
import QtQuick 2.7
import QtQuick
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.2 as Control
import QtQuick.Effects
@ -160,21 +160,28 @@ Item {
spacing: 25 * DefaultStyle.dp
Button {
visible: mainItem.groupCallVisible
Layout.fillWidth: true
Layout.preferredWidth: 320 * DefaultStyle.dp
padding: 0
background: Rectangle {
color: DefaultStyle.groupCallButtonColor
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: DefaultStyle.main2_100}
GradientStop { position: 1.0; color: DefaultStyle.grey_0}
}
anchors.fill: parent
radius: 50 * DefaultStyle.dp
}
contentItem: RowLayout {
anchors.verticalCenter: parent.verticalCenter
Image {
source: AppIcons.groupCall
Layout.preferredWidth: 35 * DefaultStyle.dp
sourceSize.width: 35 * DefaultStyle.dp
Layout.preferredWidth: 44 * DefaultStyle.dp
sourceSize.width: 44 * DefaultStyle.dp
fillMode: Image.PreserveAspectFit
}
Text {
text: "Appel de groupe"
color: DefaultStyle.grey_1000
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
@ -185,36 +192,38 @@ Item {
}
Image {
source: AppIcons.rightArrow
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
}
}
}
// RowLayout {
// //DEBUG
// visible: searchBar.text.length > 0
// Layout.maximumWidth: parent.width
// Layout.fillWidth: true
// Text {
// text: searchBar.text
// maximumLineCount: 1
// elide: Text.ElideRight
// }
// Item {
// Layout.fillWidth: true
// }
// Button {
// implicitWidth: 30 * DefaultStyle.dp
// implicitHeight: 30 * DefaultStyle.dp
// background: Item {
// visible: false
// }
// icon.source: AppIcons.phone
// width: 20 * DefaultStyle.dp
// height: 20 * DefaultStyle.dp
// onClicked: {
// mainItem.callButtonPressed(searchBar.text)
// }
// }
// //DEBUG
// visible: searchBar.text.length > 0
// Layout.maximumWidth: parent.width
// Layout.fillWidth: true
// Text {
// text: searchBar.text
// maximumLineCount: 1
// elide: Text.ElideRight
// }
// Item {
// Layout.fillWidth: true
// }
// Button {
// implicitWidth: 30 * DefaultStyle.dp
// implicitHeight: 30 * DefaultStyle.dp
// background: Item {
// visible: false
// }
// icon.source: AppIcons.phone
// width: 20 * DefaultStyle.dp
// height: 20 * DefaultStyle.dp
// onClicked: {
// mainItem.callButtonPressed(searchBar.text)
// }
// }
// }
ColumnLayout {
Text {
@ -227,10 +236,10 @@ Item {
ContactsList{
id: contactList
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
contactMenuVisible: false
searchBarText: searchBar.text
model: MagicSearchProxy {
searchText: searchBarText.length === 0 ? "*" : searchBarText
searchText: searchBar.text.length === 0 ? "*" : searchBar.text
}
onSelectedContactChanged: {
if (selectedContact) {
@ -266,10 +275,9 @@ Item {
contactMenuVisible: false
Layout.fillWidth: true
Layout.fillHeight: true
Layout.preferredHeight: contentHeight
initialHeadersVisible: false
displayNameCapitalization: false
// Align the suggestions list to the friends ones (which contains intial column)
delegateLeftMargin: 20 * DefaultStyle.dp
model: MagicSearchProxy {
searchText: searchBar.text.length === 0 ? "*" : searchBar.text
sourceFlags: LinphoneEnums.MagicSearchSource.All

View file

@ -5,7 +5,19 @@ import Linphone
Control.Page {
id: mainItem
property alias headerContent: header.children
property alias headerStack: headerStack
property alias contentStackView: contentStackView
property bool closeButtonVisible: true
clip: true
property string headerTitleText
property string headerSubtitleText
property string headerValidateButtonText
signal returnRequested()
signal validateRequested()
topPadding: 16 * DefaultStyle.dp
leftPadding: 16 * DefaultStyle.dp
background: Rectangle {
width: mainItem.width
@ -32,24 +44,93 @@ Control.Page {
width: pageHeader.width
}
}
contentItem: RowLayout {
Item {
id: header
Layout.fillWidth: true
Layout.fillHeight: true
}
Button {
id: closeButton
background: Item {
visible: false
contentItem: StackLayout {
id: headerStack
RowLayout {
Layout.alignment: Qt.AlignVCenter
Text {
text: mainItem.headerTitleText
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignVCenter
verticalAlignment: Text.AlignVCenter
color: mainWindow.conference ? DefaultStyle.main1_500_main : DefaultStyle.main2_700
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
}
Button {
id: closeButton
visible: mainItem.closeButtonVisible
background: Item {
visible: false
}
icon.source: AppIcons.closeX
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
icon.width: 24 * DefaultStyle.dp
icon.height: 24 * DefaultStyle.dp
onClicked: mainItem.visible = false
}
}
RowLayout {
Layout.alignment: Qt.AlignVCenter
spacing: 5 * DefaultStyle.dp
Button {
background: Item{}
icon.source: AppIcons.leftArrow
icon.width: 24 * DefaultStyle.dp
icon.height: 24 * DefaultStyle.dp
contentImageColor: DefaultStyle.main1_500_main
onClicked: mainItem.returnRequested()
}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
Text {
Layout.alignment: Qt.AlignVCenter
verticalAlignment: Text.AlignVCenter
text: mainItem.headerTitleText
color: DefaultStyle.main1_500_main
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
}
Text {
Layout.alignment: Qt.AlignVCenter
verticalAlignment: Text.AlignVCenter
text: mainItem.headerSubtitleText
color: DefaultStyle.main2_500main
font {
pixelSize: 12 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
Button {
text: mainItem.headerValidateButtonText
textSize: 13 * DefaultStyle.dp
textWeight: 600 * DefaultStyle.dp
onClicked: mainItem.validateRequested()
topPadding: 6 * DefaultStyle.dp
bottomPadding: 6 * DefaultStyle.dp
leftPadding: 12 * DefaultStyle.dp
rightPadding: 12 * DefaultStyle.dp
}
icon.source: AppIcons.closeX
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
icon.width: 24 * DefaultStyle.dp
icon.height: 24 * DefaultStyle.dp
onClicked: mainItem.visible = false
}
}
}
contentItem: Control.StackView {
id: contentStackView
// width: parent.width
// height: parent.height
}
}

View file

@ -6,7 +6,6 @@ import UtilsCpp 1.0
ListView {
id: mainItem
Layout.preferredHeight: contentHeight
height: contentHeight
visible: contentHeight > 0
clip: true
@ -18,7 +17,7 @@ ListView {
// dots popup menu
property bool contactMenuVisible: true
// call, video call etc menu
property bool actionMenuVisible: true
property bool actionLayoutVisible: false
property bool initialHeadersVisible: true
property bool displayNameCapitalization: true
property bool showOnlyFavourites: false
@ -35,7 +34,6 @@ ListView {
}
}
}
property int delegateLeftMargin: 0
currentIndex: -1
property FriendGui selectedContact: model.getAt(currentIndex) || null
@ -88,7 +86,7 @@ ListView {
RowLayout {
id: contactDelegate
anchors.left: initial.visible ? initial.right : parent.left
anchors.leftMargin: 10 * DefaultStyle.dp + mainItem.delegateLeftMargin
anchors.leftMargin: 10 * DefaultStyle.dp
anchors.right: parent.right
anchors.rightMargin: 10 * DefaultStyle.dp
anchors.verticalCenter: parent.verticalCenter
@ -125,14 +123,14 @@ ListView {
RowLayout {
id: actionsRow
z: 1
visible: mainItem.actionMenuVisible || friendPopup.visible
// visible: mainItem.actionLayoutVisible || friendPopup.visible
// anchors.fill: parent
anchors.right: parent.right
anchors.rightMargin: 10 * DefaultStyle.dp
anchors.verticalCenter: parent.verticalCenter
RowLayout{
property var callObj
visible: mainItem.actionMenuVisible
visible: mainItem.actionLayoutVisible
spacing: 10 * DefaultStyle.dp
Button {
Layout.preferredWidth: 24 * DefaultStyle.dp

View file

@ -15,7 +15,6 @@ ListView {
property bool hoverEnabled: true
property int delegateLeftMargin: 0
currentIndex: -1
property var delegateButtons
@ -99,8 +98,8 @@ ListView {
Rectangle {
id: conferenceInfoDelegate
anchors.left: dateDay.visible ? dateDay.right : parent.left
anchors.leftMargin: 10 * DefaultStyle.dp + mainItem.delegateLeftMargin
anchors.rightMargin: 25 * DefaultStyle.dp + mainItem.delegateLeftMargin
anchors.leftMargin: 10 * DefaultStyle.dp
anchors.rightMargin: 5 * DefaultStyle.dp
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
radius: 10 * DefaultStyle.dp
@ -142,8 +141,8 @@ ListView {
source: conferenceInfoDelegate
anchors.fill: conferenceInfoDelegate
shadowEnabled: true
shadowBlur: 1.0
shadowOpacity: 0.1
shadowBlur: 0.8
shadowOpacity: 0.2
}
MouseArea {

View file

@ -18,10 +18,6 @@ ListView {
property CallGui call
property bool hoverEnabled: true
// dots popup menu
property bool contactMenuVisible: true
// call, video call etc menu
property bool actionMenuVisible: true
property bool initialHeadersVisible: true
property bool displayNameCapitalization: true

View file

@ -20,10 +20,6 @@ ListView {
property bool isMeAdmin: me ? me.core.isAdmin : false
property bool hoverEnabled: true
// dots popup menu
property bool contactMenuVisible: true
// call, video call etc menu
property bool actionMenuVisible: true
property bool initialHeadersVisible: true
property bool displayNameCapitalization: true

View file

@ -11,12 +11,20 @@ ColumnLayout {
property string validateButtonText
property string placeHolderText: qsTr("Rechercher des contacts")
property color titleColor: DefaultStyle.main2_700
property list<string> selectedParticipants: contactList.selectedContacts
property int selectedParticipantsCount: selectedParticipants.length
property alias titleLayout: titleLayout
property ConferenceInfoGui conferenceInfoGui
signal returnRequested()
Layout.preferredWidth: 362 * DefaultStyle.dp
// Layout.preferredWidth: 362 * DefaultStyle.dp
function clearSelectedParticipants() {
contactList.selectedContacts.clear()
}
RowLayout {
Layout.preferredWidth: 362 * DefaultStyle.dp
id: titleLayout
Layout.fillWidth: true
Button {
background: Item{}
icon.source: AppIcons.leftArrow
@ -39,6 +47,7 @@ ColumnLayout {
Layout.preferredWidth: 70 * DefaultStyle.dp
topPadding: 6 * DefaultStyle.dp
bottomPadding: 6 * DefaultStyle.dp
enabled: contactList.selectedContacts.length != 0
// leftPadding: 12 * DefaultStyle.dp
// rightPadding: 12 * DefaultStyle.dp
text: mainItem.validateButtonText

View file

@ -14,11 +14,12 @@ Item {
property string noItemButtonText
property string newItemIconSource
property string emptyListText
property bool showDefaultItem: true
property color rightPanelColor: DefaultStyle.grey_100
property alias leftPanelContent: leftPanel.children
property alias rightPanelStackView: rightPanelStackView
property alias contactEditionComp: contactEditionComp
property alias rightPanel: rightPanel
property bool showDefaultItem: true
signal noItemButtonPressed()
signal contactEditionClosed()
@ -151,7 +152,7 @@ Item {
Rectangle {
id: rightPanel
clip: true
color: DefaultStyle.grey_100
color: mainItem.rightPanelColor
Layout.fillWidth: true
Layout.fillHeight: true
StackLayout {
@ -227,11 +228,13 @@ Item {
}
}
Control.StackView {
id: rightPanelStackView
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: 39 * DefaultStyle.dp
Item {
Control.StackView {
id: rightPanelStackView
anchors.fill: parent
anchors.topMargin: 39 * DefaultStyle.dp
anchors.leftMargin: 39 * DefaultStyle.dp
}
}
// We need this component here as it is used in multiple subPages (Call and Contact pages)
Component {

View file

@ -168,7 +168,9 @@ AbstractMainPage {
id: favoriteList
hoverEnabled: mainItem.leftPanelEnabled
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
showOnlyFavourites: true
contactMenuVisible: true
model: allFriends
onSelectedContactChanged: {
if (selectedContact) {
@ -207,7 +209,9 @@ AbstractMainPage {
ContactsList{
id: contactList
hoverEnabled: mainItem.leftPanelEnabled
contactMenuVisible: true
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
searchBarText: searchBar.text
model: allFriends
onSelectedContactChanged: {

View file

@ -10,19 +10,19 @@ AbstractMainPage {
noItemButtonText: qsTr("Créer une réunion")
emptyListText: qsTr("Aucune réunion")
newItemIconSource: AppIcons.plusCircle
// rightPanel.color: DefaultStyle.grey_0
rightPanelColor: selectedConference ? DefaultStyle.grey_0 : DefaultStyle.grey_100
// disable left panel contact list interaction while a contact is being edited
property bool leftPanelEnabled: true
property ConferenceInfoGui selectedConference
property int meetingListCount
signal newConfCreated()
onVisibleChanged: if (visible) rightPanelStackView.push(overridenRightPanel, Control.StackView.Immediate)
onSelectedConferenceChanged: {
if (selectedConference) {
if (!rightPanelStackView.currentItem || rightPanelStackView.currentItem.objectName != "meetingDetail") rightPanelStackView.replace(meetingDetail, Control.StackView.Immediate)
/*if (!overridenRightPanelStackView.currentItem || overridenRightPanelStackView.currentItem.objectName != "meetingDetail") */overridenRightPanelStackView.replace(meetingDetail, Control.StackView.Immediate)
} else {
if (rightPanelStackView.currentItem && rightPanelStackView.currentItem.objectName === "meetingDetail") rightPanelStackView.clear()
/*if (overridenRightPanelStackView.currentItem && overridenRightPanelStackView.currentItem.objectName === "meetingDetail")*/ overridenRightPanelStackView.clear()
}
}
@ -42,7 +42,7 @@ AbstractMainPage {
}', mainItem)
leftPanelStackView.push(createConf, {"conferenceInfoGui": confInfoGui, "isCreation": isCreation})
} else {
rightPanelStackView.push(editConf, {"conferenceInfoGui": confInfoGui, "isCreation": isCreation})
overridenRightPanelStackView.push(editConf, {"conferenceInfoGui": confInfoGui, "isCreation": isCreation})
}
}
@ -92,23 +92,25 @@ AbstractMainPage {
]
}
leftPanelContent: ColumnLayout {
leftPanelContent: RowLayout {
id: leftPanel
Layout.fillWidth: true
Layout.fillHeight: true
property int sideMargin: 25 * DefaultStyle.dp
property int sideMargin: 20 * DefaultStyle.dp
ColumnLayout {
// Layout.topMargin: 30 * DefaultStyle.dp
Layout.leftMargin: leftPanel.sideMargin
spacing: 30 * DefaultStyle.dp
// Layout.leftMargin: leftPanel.sideMargin
enabled: mainItem.leftPanelEnabled
spacing: 30 * DefaultStyle.dp
Layout.leftMargin: leftPanel.sideMargin
Layout.rightMargin: leftPanel.sideMargin
RowLayout {
visible: leftPanelStackView.currentItem.objectName == "listLayout"
Layout.fillWidth: true
Layout.rightMargin: leftPanel.sideMargin
// Layout.rightMargin: leftPanel.sideMargin
Text {
text: qsTr("Réunions")
@ -142,75 +144,87 @@ AbstractMainPage {
initialItem: listLayout
anchors.fill: parent
}
Component {
id: listLayout
ColumnLayout {
property string objectName: "listLayout"
spacing: 19 * DefaultStyle.dp
}
}
SearchBar {
id: searchBar
Layout.fillWidth: true
Layout.rightMargin: leftPanel.sideMargin
placeholderText: qsTr("Rechercher une réunion")
}
Control.ScrollBar {
id: meetingsScrollbar
visible: leftPanelStackView.currentItem.objectName == "listLayout"
active: true
interactive: true
policy: Control.ScrollBar.AsNeeded
Layout.fillHeight: true
}
}
Text {
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter
text: mainItem.emptyListText
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
visible: mainItem.showDefaultItem
}
RowLayout {
MeetingList {
id: conferenceList
visible: count != 0
hoverEnabled: mainItem.leftPanelEnabled
Layout.fillWidth: true
Layout.fillHeight: true
Layout.topMargin: 20 * DefaultStyle.dp
searchBarText: searchBar.text
onSelectedConferenceChanged: {
mainItem.selectedConference = selectedConference
}
onCountChanged: {
mainItem.meetingListCount = count
}
Connections {
target: mainItem
onNewConfCreated: {
conferenceList.forceUpdate()
}
}
Control.ScrollBar.vertical: meetingsScrollbar
}
Control.ScrollBar {
id: meetingsScrollbar
visible: leftPanelStackView.currentItem.objectName == "listLayout"
active: true
interactive: true
policy: Control.ScrollBar.AsNeeded
Layout.fillHeight: true
// anchors.top: parent.top
// anchors.bottom: parent.bottom
// anchors.right: parent.right
}
Item {
id: overridenRightPanel
Control.StackView {
id: overridenRightPanelStackView
RectangleTest{anchors.fill: parent}
width: 393 * DefaultStyle.dp
anchors.top: parent.top
// Layout.fillWidth: false
}
}
Component {
id: listLayout
ColumnLayout {
property string objectName: "listLayout"
spacing: 19 * DefaultStyle.dp
Control.StackView.onDeactivated: {
mainItem.selectedConference = null
// mainItem.righPanelStackView.clear()
}
Control.StackView.onActivated: mainItem.selectedConference = conferenceList.selectedConference
SearchBar {
id: searchBar
Layout.fillWidth: true
placeholderText: qsTr("Rechercher une réunion")
}
Text {
Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter
text: mainItem.emptyListText
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
visible: mainItem.showDefaultItem
}
RowLayout {
MeetingList {
id: conferenceList
visible: count != 0
hoverEnabled: mainItem.leftPanelEnabled
Layout.fillWidth: true
Layout.fillHeight: true
Layout.topMargin: 20 * DefaultStyle.dp
searchBarText: searchBar.text
onSelectedConferenceChanged: {
mainItem.selectedConference = selectedConference
}
onCountChanged: {
mainItem.meetingListCount = count
}
Connections {
target: mainItem
onNewConfCreated: {
conferenceList.forceUpdate()
}
}
Control.ScrollBar.vertical: meetingsScrollbar
}
}
}
}
Component {
id: createConf
MeetingSetUp {
Layout.rightMargin: leftPanel.sideMargin
id: meetingSetup
onSaveSucceed: {
mainItem.newConfCreated()
leftPanelStackView.pop()
@ -220,7 +234,7 @@ AbstractMainPage {
leftPanelStackView.pop()
}
onAddParticipantsRequested: {
leftPanelStackView.push(addParticipants, {"conferenceInfoGui": conferenceInfoGui, "container": leftPanelStackView})
leftPanelStackView.push(addParticipants, {"conferenceInfoGui": meetingSetup.conferenceInfoGui, "container": leftPanelStackView})
}
}
}
@ -230,49 +244,43 @@ AbstractMainPage {
property bool isCreation
property ConferenceInfoGui conferenceInfoGui
MeetingSetUp {
Layout.alignment: Qt.AlignTop
Layout.preferredWidth: 393 * DefaultStyle.dp
Layout.fillWidth: false
Layout.fillHeight: true
Layout.leftMargin: 39 * DefaultStyle.dp
Layout.topMargin: 39 * DefaultStyle.dp
isCreation: parent.isCreation
conferenceInfoGui: parent.conferenceInfoGui
onReturnRequested: {
mainItem.rightPanelStackView.pop()
overridenRightPanelStackView.pop()
}
onSaveSucceed: {
mainItem.rightPanelStackView.pop()
overridenRightPanelStackView.pop()
UtilsCpp.showInformationPopup(qsTr("Enregistré"), qsTr("Réunion modifiée avec succès"), true)
}
onAddParticipantsRequested: {
mainItem.rightPanelStackView.push(addParticipants, {"conferenceInfoGui": conferenceInfoGui, "container": mainItem.rightPanelStackView})
overridenRightPanelStackView.push(addParticipants, {"conferenceInfoGui": conferenceInfoGui, "container": overridenRightPanelStackView})
}
}
}
}
Component {
id: addParticipants
AddParticipantsLayout {
title: qsTr("Ajouter des participants")
validateButtonText: qsTr("Ajouter")
titleColor: DefaultStyle.main1_500_main
RowLayout {
id: addParticipantLayout
property Control.StackView container
onReturnRequested: {
container.pop()
property ConferenceInfoGui conferenceInfoGui
AddParticipantsLayout {
conferenceInfoGui: parent.conferenceInfoGui
title: qsTr("Ajouter des participants")
validateButtonText: qsTr("Ajouter")
titleColor: DefaultStyle.main1_500_main
onReturnRequested: {
addParticipantLayout.container.pop()
}
}
}
}
Component {
id: meetingDetail
RowLayout {
visible: mainItem.selectedConference
ColumnLayout {
Layout.preferredWidth: 393 * DefaultStyle.dp
Layout.alignment: Qt.AlignTop
Layout.fillWidth: false
Layout.fillHeight: true
Layout.leftMargin: 39 * DefaultStyle.dp
Layout.topMargin: 39 * DefaultStyle.dp
spacing: 25 * DefaultStyle.dp
Section {
content: RowLayout {
@ -293,12 +301,13 @@ AbstractMainPage {
Layout.fillWidth: true
}
Button {
visible: UtilsCpp.isMe(mainItem.selectedConference.core.organizerAddress)
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
icon.source: AppIcons.pencil
contentImageColor: DefaultStyle.main1_500_main
background: Item{}
onClicked: mainItem.setUpConference(mainItem.selectedConference) //mainItem.rightPanelStackView.push(meetingEdition)
onClicked: mainItem.setUpConference(mainItem.selectedConference)
}
PopupButton {
id: deletePopup
@ -524,149 +533,4 @@ AbstractMainPage {
}
}
}
// Component {
// id: meetingEdition
// RowLayout {
// ColumnLayout {
// Layout.alignment: Qt.AlignTop
// Layout.preferredWidth: 393 * DefaultStyle.dp
// Layout.fillWidth: false
// Layout.fillHeight: true
// Layout.leftMargin: 39 * DefaultStyle.dp
// Layout.topMargin: 39 * DefaultStyle.dp
// spacing: 25 * DefaultStyle.dp
// Section {
// content: RowLayout {
// spacing: 8 * DefaultStyle.dp
// Button {
// Layout.preferredWidth: 24 * DefaultStyle.dp
// Layout.preferredHeight: 24 * DefaultStyle.dp
// icon.source: AppIcons.leftArrow
// contentImageColor: DefaultStyle.main1_500_main
// background: Item{}
// onClicked: mainItem.rightPanelStackView.pop()
// }
// EffectImage {
// imageSource: AppIcons.usersThree
// Layout.preferredWidth: 24 * DefaultStyle.dp
// Layout.preferredHeight: 24 * DefaultStyle.dp
// colorizationColor: DefaultStyle.main2_600
// }
// TextInput {
// Component.onCompleted: text = mainItem.selectedConference.core.subject
// color: DefaultStyle.main2_600
// font {
// pixelSize: 20 * DefaultStyle.dp
// weight: 800 * DefaultStyle.dp
// }
// onEditingFinished: mainItem.selectedConference.core.subject = text
// }
// Item {
// Layout.fillWidth: true
// }
// Button {
// text: qsTr("Save")
// topPadding: 6 * DefaultStyle.dp
// bottomPadding: 6 * DefaultStyle.dp
// leftPadding: 12 * DefaultStyle.dp
// rightPadding: 12 * DefaultStyle.dp
// onClicked: {
// console.log("TODO : save meeting infos")
// mainItem.selectedConference.core.save()
// mainItem.rightPanelStackView.pop(meetingDetail, Control.StackView.Immediate)
// }
// }
// }
// }
// Section {
// content: [
// RowLayout {
// EffectImage {
// imageSource: AppIcons.clock
// Layout.preferredWidth: 24 * DefaultStyle.dp
// Layout.preferredHeight: 24 * DefaultStyle.dp
// colorizationColor: DefaultStyle.main2_600
// }
// Text {
// text: "All the day"
// font {
// pixelSize: 14 * DefaultStyle.dp
// weighgt: 700 * DefaultStyle.dp
// }
// }
// Item{Layout.fillWidth: true}
// Switch {
// id: isAllDaySwitch
// Component.onCompleted: if (mainItem.selectedConference.core.isAllDayConf()) toggle
// onPositionChanged: if (position === 1) {
// mainItem.selectedConference.core.dateTime = UtilsCpp.createDateTime(startDate.selectedDate, 0, 0)
// mainItem.selectedConference.core.endDateTime = UtilsCpp.createDateTime(endDate.selectedDate, 23, 59)
// }
// }
// },
// RowLayout {
// CalendarComboBox {
// id: startDate
// background: Item{}
// contentText.font.weight: 400 * DefaultStyle.dp
// Component.onCompleted: calendar.selectedDate = mainItem.selectedConference.core.dateTime
// onSelectedDateChanged: mainItem.selectedConference.core.dateTime = UtilsCpp.createDateTime(selectedDate, startHour.selectedHour, startHour.selectedMin)
// }
// Item{Layout.fillWidth: true}
// TimeComboBox {
// id: startHour
// visible: isAllDaySwitch.position === 0
// background: Item{}
// contentText.font.weight: 400 * DefaultStyle.dp
// onSelectedHourChanged: mainItem.selectedConference.core.dateTime = UtilsCpp.createDateTime(startDate.selectedDate, selectedHour, selectedMin)
// onSelectedMinChanged: mainItem.selectedConference.core.dateTime = UtilsCpp.createDateTime(startDate.selectedDate, selectedHour, selectedMin)
// }
// },
// RowLayout {
// CalendarComboBox {
// id: endDate
// background: Item{}
// contentText.font.weight: 400 * DefaultStyle.dp
// Component.onCompleted: calendar.selectedDate = mainItem.selectedConference.core.endDateTime
// onSelectedDateChanged: mainItem.selectedConference.core.endDateTime = UtilsCpp.createDateTime(selectedDate, endHour.selectedHour, endHour.selectedMin)
// }
// Item{Layout.fillWidth: true}
// TimeComboBox {
// id: endHour
// visible: isAllDaySwitch.position === 0
// background: Item{}
// contentText.font.weight: 400 * DefaultStyle.dp
// onSelectedHourChanged: mainItem.selectedConference.core.endDateTime = UtilsCpp.createDateTime(startDate.selectedDate, selectedHour, selectedMin)
// onSelectedMinChanged: mainItem.selectedConference.core.endDateTime = UtilsCpp.createDateTime(startDate.selectedDate, selectedHour, selectedMin)
// }
// },
// ComboBox {
// id: timeZoneCbox
// Layout.fillWidth: true
// Layout.preferredHeight: 30 * DefaultStyle.dp
// hoverEnabled: true
// listView.implicitHeight: 152 * DefaultStyle.dp
// constantImageSource: AppIcons.globe
// weight: 700 * DefaultStyle.dp
// leftMargin: 0
// currentIndex: mainItem.conferenceInfoGui ? model.getIndex(mainItem.conferenceInfoGui.core.timeZoneModel) : -1
// background: Rectangle {
// visible: parent.hovered || parent.down
// anchors.fill: parent
// color: DefaultStyle.grey_100
// }
// model: TimeZoneProxy{
// }
// onCurrentIndexChanged: {
// var modelIndex = timeZoneCbox.model.index(currentIndex, 0)
// mainItem.conferenceInfoGui.core.timeZoneModel = timeZoneCbox.model.data(modelIndex, Qt.DisplayRole + 1)
// }
// },
// ]
// }
// // Item{Layout.fillHeight: true}
// }
// }
// }
}