conference + ui fixes

try to fix crashes on close app
This commit is contained in:
Gaelle Braud 2024-05-13 15:35:21 +02:00
parent 0646040d25
commit 5cf6138bdb
30 changed files with 726 additions and 485 deletions

View file

@ -143,9 +143,6 @@ void App::init() {
coreModel->start(); coreModel->start();
auto settings = Settings::create(); auto settings = Settings::create();
QMetaObject::invokeMethod(App::getInstance()->thread(), [this, settings]() mutable { QMetaObject::invokeMethod(App::getInstance()->thread(), [this, settings]() mutable {
mSettings = settings;
settings.reset();
// QML // QML
mEngine = new QQmlApplicationEngine(this); mEngine = new QQmlApplicationEngine(this);
// Provide `+custom` folders for custom components and `5.9` for old components. // Provide `+custom` folders for custom components and `5.9` for old components.
@ -164,6 +161,8 @@ void App::init() {
// Enable notifications. // Enable notifications.
mNotifier = new Notifier(mEngine); mNotifier = new Notifier(mEngine);
mSettings = settings;
settings.reset();
const QUrl url(u"qrc:/Linphone/view/App/Main.qml"_qs); const QUrl url(u"qrc:/Linphone/view/App/Main.qml"_qs);
QObject::connect( QObject::connect(
@ -261,15 +260,15 @@ void App::initCppInterfaces() {
//------------------------------------------------------------ //------------------------------------------------------------
void App::clean() { void App::clean() {
if (mSettings) mSettings.reset();
// Wait 500ms to let time for log te be stored. // Wait 500ms to let time for log te be stored.
// mNotifier destroyed in mEngine deletion as it is its parent // mNotifier destroyed in mEngine deletion as it is its parent
delete mEngine; delete mEngine;
mEngine = nullptr; mEngine = nullptr;
if (mSettings) { // if (mSettings) {
mSettings = nullptr; // mSettings.reset();
} // }
mLinphoneThread->wait(250); qApp->processEvents(QEventLoop::AllEvents, 500);
qApp->processEvents(QEventLoop::AllEvents, 250);
mLinphoneThread->exit(); mLinphoneThread->exit();
mLinphoneThread->wait(); mLinphoneThread->wait();
delete mLinphoneThread; delete mLinphoneThread;

View file

@ -20,6 +20,7 @@
#include "CallHistoryCore.hpp" #include "CallHistoryCore.hpp"
#include "core/App.hpp" #include "core/App.hpp"
#include "core/conference/ConferenceInfoCore.hpp"
#include "model/call-history/CallHistoryModel.hpp" #include "model/call-history/CallHistoryModel.hpp"
#include "model/object/VariantObject.hpp" #include "model/object/VariantObject.hpp"
#include "model/tool/ToolModel.hpp" #include "model/tool/ToolModel.hpp"
@ -54,7 +55,7 @@ CallHistoryCore::CallHistoryCore(const std::shared_ptr<linphone::CallLog> &callL
mIsConference = callLog->wasConference(); mIsConference = callLog->wasConference();
if (mIsConference) { if (mIsConference) {
auto confinfo = callLog->getConferenceInfo(); auto confinfo = callLog->getConferenceInfo();
confinfo->getSubject(); mConferenceInfo = ConferenceInfoCore::create(confinfo);
mRemoteAddress = Utils::coreStringToAppString(confinfo->getUri()->asStringUriOnly()); mRemoteAddress = Utils::coreStringToAppString(confinfo->getUri()->asStringUriOnly());
mDisplayName = Utils::coreStringToAppString(confinfo->getSubject()); mDisplayName = Utils::coreStringToAppString(confinfo->getSubject());
} else { } else {
@ -73,6 +74,10 @@ void CallHistoryCore::setSelf(QSharedPointer<CallHistoryCore> me) {
new SafeConnection<CallHistoryCore, CallHistoryModel>(me, mCallHistoryModel), &QObject::deleteLater); new SafeConnection<CallHistoryCore, CallHistoryModel>(me, mCallHistoryModel), &QObject::deleteLater);
} }
ConferenceInfoGui *CallHistoryCore::getConferenceInfoGui() const {
return mConferenceInfo ? new ConferenceInfoGui(mConferenceInfo) : nullptr;
}
QString CallHistoryCore::getDuration() const { QString CallHistoryCore::getDuration() const {
return mDuration; return mDuration;
} }

View file

@ -21,6 +21,7 @@
#ifndef CALL_HISTORY_CORE_H_ #ifndef CALL_HISTORY_CORE_H_
#define CALL_HISTORY_CORE_H_ #define CALL_HISTORY_CORE_H_
#include "core/conference/ConferenceInfoGui.hpp"
#include "tool/LinphoneEnums.hpp" #include "tool/LinphoneEnums.hpp"
#include "tool/thread/SafeConnection.hpp" #include "tool/thread/SafeConnection.hpp"
#include <QDateTime> #include <QDateTime>
@ -37,6 +38,7 @@ class CallHistoryCore : public QObject, public AbstractObject {
Q_PROPERTY(QString remoteAddress MEMBER mRemoteAddress CONSTANT) Q_PROPERTY(QString remoteAddress MEMBER mRemoteAddress CONSTANT)
Q_PROPERTY(bool isOutgoing MEMBER mIsOutgoing CONSTANT) Q_PROPERTY(bool isOutgoing MEMBER mIsOutgoing CONSTANT)
Q_PROPERTY(bool isConference MEMBER mIsConference CONSTANT) Q_PROPERTY(bool isConference MEMBER mIsConference CONSTANT)
Q_PROPERTY(ConferenceInfoGui *conferenceInfo READ getConferenceInfoGui CONSTANT)
Q_PROPERTY(QDateTime date MEMBER mDate CONSTANT) Q_PROPERTY(QDateTime date MEMBER mDate CONSTANT)
Q_PROPERTY(LinphoneEnums::CallStatus status MEMBER mStatus CONSTANT) Q_PROPERTY(LinphoneEnums::CallStatus status MEMBER mStatus CONSTANT)
Q_PROPERTY(QString duration READ getDuration WRITE setDuration NOTIFY durationChanged) Q_PROPERTY(QString duration READ getDuration WRITE setDuration NOTIFY durationChanged)
@ -47,6 +49,7 @@ public:
~CallHistoryCore(); ~CallHistoryCore();
void setSelf(QSharedPointer<CallHistoryCore> me); void setSelf(QSharedPointer<CallHistoryCore> me);
ConferenceInfoGui *getConferenceInfoGui() const;
QString getDuration() const; QString getDuration() const;
void setDuration(const QString &duration); void setDuration(const QString &duration);
@ -57,7 +60,7 @@ public:
QString mDisplayName; QString mDisplayName;
QDateTime mDate; QDateTime mDate;
bool mIsOutgoing; bool mIsOutgoing;
bool mIsConference; bool mIsConference = false;
LinphoneEnums::CallStatus mStatus; LinphoneEnums::CallStatus mStatus;
signals: signals:
@ -65,7 +68,7 @@ signals:
private: private:
QString mDuration; QString mDuration;
QSharedPointer<ConferenceInfoCore> mConferenceInfo = nullptr;
std::shared_ptr<CallHistoryModel> mCallHistoryModel; std::shared_ptr<CallHistoryModel> mCallHistoryModel;
QSharedPointer<SafeConnection<CallHistoryCore, CallHistoryModel>> mHistoryModelConnection; QSharedPointer<SafeConnection<CallHistoryCore, CallHistoryModel>> mHistoryModelConnection;

View file

@ -88,14 +88,16 @@ CallCore::CallCore(const std::shared_ptr<linphone::Call> &call) : QObject(nullpt
mSpeakerVolumeGain = mCallModel->getSpeakerVolumeGain(); mSpeakerVolumeGain = mCallModel->getSpeakerVolumeGain();
// TODO : change this with settings value when settings done // TODO : change this with settings value when settings done
if (mSpeakerVolumeGain < 0) { if (mSpeakerVolumeGain < 0) {
call->setSpeakerVolumeGain(0.5); auto vol = CoreModel::getInstance()->getCore()->getPlaybackGainDb();
mSpeakerVolumeGain = 0.5; call->setSpeakerVolumeGain(vol);
mSpeakerVolumeGain = vol;
} }
mMicrophoneVolumeGain = call->getMicrophoneVolumeGain(); mMicrophoneVolumeGain = call->getMicrophoneVolumeGain();
// TODO : change this with settings value when settings done // TODO : change this with settings value when settings done
if (mMicrophoneVolumeGain < 0) { if (mMicrophoneVolumeGain < 0) {
call->setMicrophoneVolumeGain(0.5); auto vol = CoreModel::getInstance()->getCore()->getMicGainDb();
mMicrophoneVolumeGain = 0.5; call->setMicrophoneVolumeGain(vol);
mMicrophoneVolumeGain = vol;
} }
mMicrophoneVolume = call->getRecordVolume(); mMicrophoneVolume = call->getRecordVolume();
mRecordable = mState == LinphoneEnums::CallState::StreamsRunning; mRecordable = mState == LinphoneEnums::CallState::StreamsRunning;
@ -163,6 +165,12 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
mCallModelConnection->makeConnectToModel(&CallModel::durationChanged, [this](int duration) { mCallModelConnection->makeConnectToModel(&CallModel::durationChanged, [this](int duration) {
mCallModelConnection->invokeToCore([this, duration]() { setDuration(duration); }); mCallModelConnection->invokeToCore([this, duration]() { setDuration(duration); });
}); });
mCallModelConnection->makeConnectToModel(&CallModel::speakerVolumeGainChanged, [this](float volume) {
mCallModelConnection->invokeToCore([this, volume]() { setSpeakerVolumeGain(volume); });
});
mCallModelConnection->makeConnectToModel(&CallModel::microphoneVolumeGainChanged, [this](float volume) {
mCallModelConnection->invokeToCore([this, volume]() { setMicrophoneVolumeGain(volume); });
});
mCallModelConnection->makeConnectToModel(&CallModel::microphoneVolumeChanged, [this](float volume) { mCallModelConnection->makeConnectToModel(&CallModel::microphoneVolumeChanged, [this](float volume) {
mCallModelConnection->invokeToCore([this, volume]() { setMicrophoneVolume(volume); }); mCallModelConnection->invokeToCore([this, volume]() { setMicrophoneVolume(volume); });
}); });
@ -175,12 +183,26 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
mCallModelConnection->makeConnectToModel(&CallModel::statusChanged, [this](linphone::Call::Status status) { mCallModelConnection->makeConnectToModel(&CallModel::statusChanged, [this](linphone::Call::Status status) {
mCallModelConnection->invokeToCore([this, status]() { setStatus(LinphoneEnums::fromLinphone(status)); }); mCallModelConnection->invokeToCore([this, status]() { setStatus(LinphoneEnums::fromLinphone(status)); });
}); });
mCallModelConnection->makeConnectToModel(&CallModel::stateChanged, mCallModelConnection->makeConnectToModel(
[this](linphone::Call::State state, const std::string &message) { &CallModel::stateChanged, [this](linphone::Call::State state, const std::string &message) {
mCallModelConnection->invokeToCore([this, state]() { double speakerVolume = mSpeakerVolumeGain;
setRecordable(state == linphone::Call::State::StreamsRunning); double micVolume = mMicrophoneVolumeGain;
}); if (state == linphone::Call::State::StreamsRunning) {
}); speakerVolume = mCallModel->getSpeakerVolumeGain();
if (speakerVolume < 0) {
speakerVolume = CoreModel::getInstance()->getCore()->getPlaybackGainDb();
}
micVolume = mCallModel->getMicrophoneVolumeGain();
if (micVolume < 0) {
micVolume = CoreModel::getInstance()->getCore()->getMicGainDb();
}
}
mCallModelConnection->invokeToCore([this, state, speakerVolume, micVolume]() {
setSpeakerVolumeGain(speakerVolume);
setMicrophoneVolumeGain(micVolume);
setRecordable(state == linphone::Call::State::StreamsRunning);
});
});
mCallModelConnection->makeConnectToCore(&CallCore::lSetPaused, [this](bool paused) { mCallModelConnection->makeConnectToCore(&CallCore::lSetPaused, [this](bool paused) {
mCallModelConnection->invokeToModel([this, paused]() { mCallModel->setPaused(paused); }); mCallModelConnection->invokeToModel([this, paused]() { mCallModel->setPaused(paused); });
}); });
@ -319,7 +341,10 @@ void CallCore::setState(LinphoneEnums::CallState state, const QString &message)
mustBeInMainThread(log().arg(Q_FUNC_INFO)); mustBeInMainThread(log().arg(Q_FUNC_INFO));
if (mState != state) { if (mState != state) {
mState = state; mState = state;
if (state == LinphoneEnums::CallState::Error) setLastErrorMessage(message); if (state == LinphoneEnums::CallState::Error) {
lDebug() << "[CallCore] Error message : " << message;
setLastErrorMessage(message);
}
emit stateChanged(mState); emit stateChanged(mState);
} }
} }

View file

@ -58,18 +58,26 @@ void ConferenceCore::setSelf(QSharedPointer<ConferenceCore> me) {
auto device = ParticipantDeviceCore::create(participantDevice); auto device = ParticipantDeviceCore::create(participantDevice);
mConferenceModelConnection->invokeToCore([this, device]() { setActiveSpeaker(device); }); mConferenceModelConnection->invokeToCore([this, device]() { setActiveSpeaker(device); });
}); });
mConferenceModelConnection->makeConnectToModel( mConferenceModelConnection->makeConnectToModel(&ConferenceModel::participantDeviceAdded, [this]() {
&ConferenceModel::participantDeviceAdded, int count = mConferenceModel->getParticipantDeviceCount();
[this](const std::shared_ptr<linphone::ParticipantDevice> &participantDevice) { mConferenceModelConnection->invokeToCore([this, count]() { setParticipantDeviceCount(count); });
int count = mConferenceModel->getParticipantDeviceCount(); });
mConferenceModelConnection->invokeToCore([this, count]() { setParticipantDeviceCount(count); }); mConferenceModelConnection->makeConnectToModel(&ConferenceModel::participantDeviceRemoved, [this]() {
}); int count = mConferenceModel->getParticipantDeviceCount();
mConferenceModelConnection->makeConnectToModel( mConferenceModelConnection->invokeToCore([this, count]() { setParticipantDeviceCount(count); });
&ConferenceModel::participantDeviceRemoved, });
[this](const std::shared_ptr<const linphone::ParticipantDevice> &participantDevice) { mConferenceModelConnection->makeConnectToModel(&ConferenceModel::participantAdded, [this]() {
int count = mConferenceModel->getParticipantDeviceCount(); int count = mConferenceModel->getParticipantDeviceCount();
mConferenceModelConnection->invokeToCore([this, count]() { setParticipantDeviceCount(count); }); mConferenceModelConnection->invokeToCore([this, count]() { setParticipantDeviceCount(count); });
}); });
mConferenceModelConnection->makeConnectToModel(&ConferenceModel::participantRemoved, [this]() {
int count = mConferenceModel->getParticipantDeviceCount();
mConferenceModelConnection->invokeToCore([this, count]() { setParticipantDeviceCount(count); });
});
mConferenceModelConnection->makeConnectToModel(&ConferenceModel::participantDeviceStateChanged, [this]() {
int count = mConferenceModel->getParticipantDeviceCount();
mConferenceModelConnection->invokeToCore([this, count]() { setParticipantDeviceCount(count); });
});
} }
bool ConferenceCore::updateLocalParticipant() { // true if changed bool ConferenceCore::updateLocalParticipant() { // true if changed
@ -94,6 +102,9 @@ void ConferenceCore::setParticipantDeviceCount(int count) {
} }
} }
/**
* /!\ mParticipantDeviceCount retrieves all devices but mine
**/
int ConferenceCore::getParticipantDeviceCount() const { int ConferenceCore::getParticipantDeviceCount() const {
return mParticipantDeviceCount; return mParticipantDeviceCount;
} }

View file

@ -41,6 +41,7 @@ public:
// Q_PROPERTY(ParticipantDeviceList *participantDevices READ getParticipantDeviceList CONSTANT) // Q_PROPERTY(ParticipantDeviceList *participantDevices READ getParticipantDeviceList CONSTANT)
// Q_PROPERTY(ParticipantModel* localParticipant READ getLocalParticipant NOTIFY localParticipantChanged) // Q_PROPERTY(ParticipantModel* localParticipant READ getLocalParticipant NOTIFY localParticipantChanged)
Q_PROPERTY(bool isReady MEMBER mIsReady WRITE setIsReady NOTIFY isReadyChanged) Q_PROPERTY(bool isReady MEMBER mIsReady WRITE setIsReady NOTIFY isReadyChanged)
Q_PROPERTY(QString subject MEMBER mSubject CONSTANT)
Q_PROPERTY(int participantDeviceCount READ getParticipantDeviceCount NOTIFY participantDeviceCountChanged) Q_PROPERTY(int participantDeviceCount READ getParticipantDeviceCount NOTIFY participantDeviceCountChanged)
Q_PROPERTY(ParticipantDeviceGui *activeSpeaker READ getActiveSpeakerGui NOTIFY activeSpeakerChanged) Q_PROPERTY(ParticipantDeviceGui *activeSpeaker READ getActiveSpeakerGui NOTIFY activeSpeakerChanged)
Q_PROPERTY(ParticipantGui *me READ getMeGui) Q_PROPERTY(ParticipantGui *me READ getMeGui)

View file

@ -44,6 +44,7 @@ public:
Q_PROPERTY(QDateTime dateTime READ getDateTimeSystem WRITE setDateTime NOTIFY dateTimeChanged) Q_PROPERTY(QDateTime dateTime READ getDateTimeSystem WRITE setDateTime NOTIFY dateTimeChanged)
Q_PROPERTY(QDateTime endDateTime READ getEndDateTime WRITE setEndDateTime NOTIFY endDateTimeChanged) Q_PROPERTY(QDateTime endDateTime READ getEndDateTime WRITE setEndDateTime NOTIFY endDateTimeChanged)
Q_PROPERTY(QDateTime dateTimeUtc READ getDateTimeUtc NOTIFY dateTimeChanged) Q_PROPERTY(QDateTime dateTimeUtc READ getDateTimeUtc NOTIFY dateTimeChanged)
Q_PROPERTY(QString startEndDateString READ getStartEndDateString NOTIFY dateTimeChanged)
Q_PROPERTY(int duration READ getDuration WRITE setDuration NOTIFY durationChanged) Q_PROPERTY(int duration READ getDuration WRITE setDuration NOTIFY durationChanged)
Q_PROPERTY( Q_PROPERTY(
QString organizerAddress READ getOrganizerAddress WRITE setOrganizerAddress NOTIFY organizerAddressChanged) QString organizerAddress READ getOrganizerAddress WRITE setOrganizerAddress NOTIFY organizerAddressChanged)

View file

@ -83,7 +83,7 @@ bool ConferenceInfoProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sou
return res; return res;
} else return mFilterType == -1; } else return mFilterType == -1;
} else { } else {
return !mList->haveCurrentDate(); return !mList->haveCurrentDate() &&
mList->getCount() > 1; // if mlist count == 1 there is only the dummy row which we don't display alone
} }
return false;
} }

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#4e6074" viewBox="0 0 256 256"><path d="M192,40v64a8,8,0,0,1-2.34,5.66L136,163.31v49.38l18.34-18.35a8,8,0,0,1,11.32,11.32l-32,32a8,8,0,0,1-11.32,0l-32-32a8,8,0,0,1,11.32-11.32L120,212.69V163.31L66.34,109.66A8,8,0,0,1,64,104V40a8,8,0,0,1,16,0v60.69l48,48,48-48V40a8,8,0,0,1,16,0Z"></path></svg>

After

Width:  |  Height:  |  Size: 362 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#4e6074" viewBox="0 0 256 256"><path d="M53.92,34.62A8,8,0,1,0,42.08,45.38l13.18,14.5A99.39,99.39,0,0,0,32,124v84a16,16,0,0,0,16,16h84a100.33,100.33,0,0,0,56.53-17.53l13.55,14.91a8,8,0,1,0,11.84-10.76ZM132,208H48V124A83.46,83.46,0,0,1,66.15,71.85L177.66,194.51A83,83,0,0,1,132,208Zm100-84a99.87,99.87,0,0,1-14.35,51.65,8,8,0,0,1-13.7-8.28A84,84,0,0,0,95.66,48.25a8,8,0,0,1-6.94-14.42A100,100,0,0,1,232,124Z"></path></svg>

After

Width:  |  Height:  |  Size: 490 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Z"></path></svg>

After

Width:  |  Height:  |  Size: 299 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#4e6074" viewBox="0 0 256 256"><path d="M208,40H48A24,24,0,0,0,24,64V176a24,24,0,0,0,24,24H208a24,24,0,0,0,24-24V64A24,24,0,0,0,208,40Zm8,136a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V64a8,8,0,0,1,8-8H208a8,8,0,0,1,8,8Zm-48,48a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,224ZM157.66,106.34a8,8,0,0,1-11.32,11.32L136,107.31V152a8,8,0,0,1-16,0V107.31l-10.34,10.35a8,8,0,0,1-11.32-11.32l24-24a8,8,0,0,1,11.32,0Z"></path></svg>

After

Width:  |  Height:  |  Size: 486 B

View file

@ -204,7 +204,6 @@ void CallModel::setSpeakerVolumeGain(float gain) {
float CallModel::getSpeakerVolumeGain() const { float CallModel::getSpeakerVolumeGain() const {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
auto gain = mMonitor->getSpeakerVolumeGain(); auto gain = mMonitor->getSpeakerVolumeGain();
if (gain < 0) gain = CoreModel::getInstance()->getCore()->getPlaybackGainDb();
return gain; return gain;
} }

View file

@ -99,6 +99,7 @@ void Utils::createCall(const QString &sipAddress,
QVariantMap options, QVariantMap options,
const QString &prepareTransfertAddress, const QString &prepareTransfertAddress,
const QHash<QString, QString> &headers) { const QHash<QString, QString> &headers) {
lDebug() << "[Utils] create call with uri :" << sipAddress;
App::postModelAsync([sipAddress, options, prepareTransfertAddress, headers]() { App::postModelAsync([sipAddress, options, prepareTransfertAddress, headers]() {
QString errorMessage; QString errorMessage;
bool success = ToolModel::createCall(sipAddress, options, prepareTransfertAddress, headers, bool success = ToolModel::createCall(sipAddress, options, prepareTransfertAddress, headers,
@ -352,8 +353,16 @@ int Utils::getRandomIndex(int size) {
return QRandomGenerator::global()->bounded(size); return QRandomGenerator::global()->bounded(size);
} }
void Utils::copyToClipboard(const QString &text) { bool Utils::copyToClipboard(const QString &text) {
QApplication::clipboard()->setText(text); QClipboard *clipboard = QApplication::clipboard();
clipboard->clear();
clipboard->setText(text);
QString clipboardText = clipboard->text();
if (clipboardText.isEmpty()) {
lDebug() << "[Utils] Clipboard is empty!";
}
return !clipboardText.isEmpty();
} }
QString Utils::getApplicationProduct() { QString Utils::getApplicationProduct() {

View file

@ -69,7 +69,7 @@ public:
const QString &description, const QString &description,
bool isSuccess = true, bool isSuccess = true,
QQuickWindow *window = nullptr); QQuickWindow *window = nullptr);
Q_INVOKABLE static QQuickWindow *getCallsWindow(CallGui *callGui); Q_INVOKABLE static QQuickWindow *getCallsWindow(CallGui *callGui = nullptr);
Q_INVOKABLE static void closeCallsWindow(); Q_INVOKABLE static void closeCallsWindow();
Q_INVOKABLE static VariantObject *haveAccount(); Q_INVOKABLE static VariantObject *haveAccount();
Q_INVOKABLE static void smartShowWindow(QQuickWindow *window); Q_INVOKABLE static void smartShowWindow(QQuickWindow *window);
@ -80,7 +80,7 @@ public:
Q_INVOKABLE static QString formatDateElapsedTime(const QDateTime &date); Q_INVOKABLE static QString formatDateElapsedTime(const QDateTime &date);
Q_INVOKABLE static QStringList generateSecurityLettersArray(int arraySize, int correctIndex, QString correctCode); Q_INVOKABLE static QStringList generateSecurityLettersArray(int arraySize, int correctIndex, QString correctCode);
Q_INVOKABLE static int getRandomIndex(int size); Q_INVOKABLE static int getRandomIndex(int size);
Q_INVOKABLE static void copyToClipboard(const QString &text); Q_INVOKABLE static bool copyToClipboard(const QString &text);
Q_INVOKABLE static QString toDateString(QDateTime date, const QString &format = ""); Q_INVOKABLE static QString toDateString(QDateTime date, const QString &format = "");
Q_INVOKABLE static QString toDateString(QDate date, const QString &format = ""); Q_INVOKABLE static QString toDateString(QDate date, const QString &format = "");
Q_INVOKABLE static QString toDateDayString(const QDateTime &date); Q_INVOKABLE static QString toDateDayString(const QDateTime &date);

View file

@ -15,66 +15,25 @@ AppWindow {
// modality: Qt.WindowModal // modality: Qt.WindowModal
property CallGui call property CallGui call
property ConferenceInfoGui conferenceInfo
property ConferenceGui conference: call && call.core.conference || null property ConferenceGui conference: call && call.core.conference || null
property int conferenceLayout: call && call.core.conferenceVideoLayout || 0 property int conferenceLayout: call && call.core.conferenceVideoLayout || 0
property bool callTerminatedByUser: false property bool callTerminatedByUser: false
property var callState: call && call.core.state
property var transferState: call && call.core.transferState
onCallChanged: { onCallChanged: {
// if conference, the main item is only // if conference, the main item is only
// displayed when state is connected // displayed when state is connected
if (call && middleItemStackView.currentItem != inCallItem if (call && middleItemStackView.currentItem != inCallItem && conference)
&& (!conferenceInfo || conference) )
middleItemStackView.replace(inCallItem) middleItemStackView.replace(inCallItem)
} }
function joinConference(options) {
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 {
UtilsCpp.createCall(conferenceInfo.core.uri, options)
}
}
function shareInvitation() {
UtilsCpp.copyToClipboard(conference.core.uri)
showInformationPopup(qsTr("Copié"), qsTr("Le lien de la réunion a été copié dans le presse-papier"), true)
}
function changeLayout(layoutIndex) {
if (layoutIndex == 0) {
console.log("Set Grid layout")
call.core.lSetConferenceVideoLayout(LinphoneEnums.ConferenceLayout.Grid)
} else if (layoutIndex == 1) {
console.log("Set AS layout")
call.core.lSetConferenceVideoLayout(LinphoneEnums.ConferenceLayout.ActiveSpeaker)
} else {
console.log("Set audio-only layout")
call.core.lSetConferenceVideoLayout(LinphoneEnums.ConferenceLayout.AudioOnly)
}
}
Connections {
enabled: !!call
target: call && call.core
onRemoteVideoEnabledChanged: console.log("remote video enabled", call.core.remoteVideoEnabled)
onSecurityUpdated: {
if (call.core.isSecured) {
zrtpValidation.close()
}
else if(call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp) {
zrtpValidation.open()
// mainWindow.attachVirtualWindow(Utils.buildLinphoneDialogUri('ZrtpTokenAuthenticationDialog'), {call:callModel})
}
}
}
property var callState: call && call.core.state
onCallStateChanged: { onCallStateChanged: {
if (callState === LinphoneEnums.CallState.Connected) { if (callState === LinphoneEnums.CallState.Connected) {
if (conferenceInfo && middleItemStackView.currentItem != inCallItem) { if (middleItemStackView.currentItem != inCallItem) {
middleItemStackView.replace(inCallItem) middleItemStackView.replace(inCallItem)
bottomButtonsLayout.visible = true bottomButtonsLayout.visible = true
} }
@ -86,7 +45,6 @@ AppWindow {
callEnded(call) callEnded(call)
} }
} }
property var transferState: call && call.core.transferState
onTransferStateChanged: { onTransferStateChanged: {
console.log("Transfer state:", transferState) console.log("Transfer state:", transferState)
if (transferState === LinphoneEnums.CallState.Error) { if (transferState === LinphoneEnums.CallState.Error) {
@ -106,12 +64,17 @@ AppWindow {
} }
} }
Timer { function changeLayout(layoutIndex) {
id: autoCloseWindow if (layoutIndex == 0) {
interval: 2000 console.log("Set Grid layout")
onTriggered: { call.core.lSetConferenceVideoLayout(LinphoneEnums.ConferenceLayout.Grid)
UtilsCpp.closeCallsWindow() } else if (layoutIndex == 1) {
} console.log("Set AS layout")
call.core.lSetConferenceVideoLayout(LinphoneEnums.ConferenceLayout.ActiveSpeaker)
} else {
console.log("Set audio-only layout")
call.core.lSetConferenceVideoLayout(LinphoneEnums.ConferenceLayout.AudioOnly)
}
} }
function endCall(callToFinish) { function endCall(callToFinish) {
@ -119,7 +82,7 @@ AppWindow {
} }
function callEnded(call){ function callEnded(call){
if (!callsModel.haveCall) { if (!callsModel.haveCall) {
if (call.core.conference) UtilsCpp.closeCallsWindow() if (call && call.core.conference) UtilsCpp.closeCallsWindow()
else { else {
bottomButtonsLayout.setButtonsEnabled(false) bottomButtonsLayout.setButtonsEnabled(false)
autoCloseWindow.restart() autoCloseWindow.restart()
@ -129,6 +92,50 @@ AppWindow {
} }
} }
signal setUpConferenceRequested(ConferenceInfoGui conferenceInfo)
function setupConference(conferenceInfo) {
middleItemStackView.replace(waitingRoom)
setUpConferenceRequested(conferenceInfo)
}
function joinConference(uri, options) {
if (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 {
UtilsCpp.createCall(uri, options)
}
}
function cancelJoinConference() {
if (!callsModel.haveCall) {
UtilsCpp.closeCallsWindow()
} else {
mainWindow.call = callsModel.currentCall
}
middleItemStackView.replace(inCallItem)
}
Connections {
enabled: !!call
target: call && call.core
onRemoteVideoEnabledChanged: console.log("remote video enabled", call.core.remoteVideoEnabled)
onSecurityUpdated: {
if (call.core.isSecured) {
zrtpValidation.close()
}
else if(call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp) {
zrtpValidation.open()
// mainWindow.attachVirtualWindow(Utils.buildLinphoneDialogUri('ZrtpTokenAuthenticationDialog'), {call:callModel})
}
}
}
Timer {
id: autoCloseWindow
interval: 2000
onTriggered: {
UtilsCpp.closeCallsWindow()
}
}
Dialog { Dialog {
id: terminateAllCallsDialog id: terminateAllCallsDialog
onAccepted: call.core.lTerminateAllCalls() onAccepted: call.core.lTerminateAllCalls()
@ -250,128 +257,144 @@ AppWindow {
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: 10 * DefaultStyle.dp spacing: 10 * DefaultStyle.dp
EffectImage { ColumnLayout {
id: callStatusIcon RowLayout {
Layout.preferredWidth: 30 * DefaultStyle.dp spacing: 10 * DefaultStyle.dp
Layout.preferredHeight: 30 * DefaultStyle.dp EffectImage {
// TODO : change with broadcast or meeting icon when available id: callStatusIcon
imageSource: !mainWindow.call Layout.preferredWidth: 30 * DefaultStyle.dp
? AppIcons.meeting Layout.preferredHeight: 30 * DefaultStyle.dp
: (mainWindow.callState === LinphoneEnums.CallState.End // TODO : change with broadcast or meeting icon when available
|| mainWindow.callState === LinphoneEnums.CallState.Released) imageSource: !mainWindow.call
? AppIcons.endCall ? AppIcons.meeting
: (mainWindow.callState === LinphoneEnums.CallState.Paused : (mainWindow.callState === LinphoneEnums.CallState.End
|| mainWindow.callState === LinphoneEnums.CallState.PausedByRemote) || mainWindow.callState === LinphoneEnums.CallState.Released)
? AppIcons.pause ? AppIcons.endCall
: mainWindow.conferenceInfo : (mainWindow.callState === LinphoneEnums.CallState.Paused
? AppIcons.usersThree || mainWindow.callState === LinphoneEnums.CallState.PausedByRemote)
: mainWindow.call.core.dir === LinphoneEnums.CallDir.Outgoing ? AppIcons.pause
? AppIcons.arrowUpRight : mainWindow.conference
: AppIcons.arrowDownLeft ? AppIcons.usersThree
colorizationColor: !mainWindow.call || mainWindow.callState === LinphoneEnums.CallState.Paused : mainWindow.call.core.dir === LinphoneEnums.CallDir.Outgoing
|| mainWindow.callState === LinphoneEnums.CallState.PausedByRemote || mainWindow.callState === LinphoneEnums.CallState.End ? AppIcons.arrowUpRight
|| mainWindow.callState === LinphoneEnums.CallState.Released || mainWindow.conferenceInfo : AppIcons.arrowDownLeft
? DefaultStyle.danger_500main colorizationColor: !mainWindow.call || mainWindow.callState === LinphoneEnums.CallState.Paused
: mainWindow.call.core.dir === LinphoneEnums.CallDir.Outgoing || mainWindow.callState === LinphoneEnums.CallState.PausedByRemote || mainWindow.callState === LinphoneEnums.CallState.End
? DefaultStyle.info_500_main || mainWindow.callState === LinphoneEnums.CallState.Released || mainWindow.conference
: DefaultStyle.success_500main ? DefaultStyle.danger_500main
} : mainWindow.call.core.dir === LinphoneEnums.CallDir.Outgoing
Text { ? DefaultStyle.info_500_main
id: callStatusText : DefaultStyle.success_500main
text: (mainWindow.callState === LinphoneEnums.CallState.End || mainWindow.callState === LinphoneEnums.CallState.Released) }
? qsTr("End of the call") Text {
: (mainWindow.callState === LinphoneEnums.CallState.Paused id: callStatusText
|| mainWindow.callState === LinphoneEnums.CallState.PausedByRemote) text: (mainWindow.callState === LinphoneEnums.CallState.End || mainWindow.callState === LinphoneEnums.CallState.Released)
? qsTr("Appel mis en pause") ? qsTr("End of the call")
: mainWindow.conferenceInfo : (mainWindow.callState === LinphoneEnums.CallState.Paused
? mainWindow.conferenceInfo.core.subject || mainWindow.callState === LinphoneEnums.CallState.PausedByRemote)
: mainWindow.call ? (mainWindow.conference ? qsTr('Réunion mise ') : qsTr('Appel mis')) + qsTr(" en pause")
? EnumsToStringCpp.dirToString(mainWindow.call.core.dir) + qsTr(" call") : mainWindow.conference
: "" ? mainWindow.conference.core.subject
color: DefaultStyle.grey_0 : mainWindow.call
font { ? EnumsToStringCpp.dirToString(mainWindow.call.core.dir) + qsTr(" call")
pixelSize: 22 * DefaultStyle.dp : ""
weight: 800 * DefaultStyle.dp color: DefaultStyle.grey_0
font {
pixelSize: 22 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
}
Rectangle {
visible: mainWindow.call && (mainWindow.callState === LinphoneEnums.CallState.Connected
|| mainWindow.callState === LinphoneEnums.CallState.StreamsRunning)
Layout.preferredHeight: parent.height
Layout.preferredWidth: 2 * DefaultStyle.dp
color: DefaultStyle.grey_0
}
Text {
text: mainWindow.call ? UtilsCpp.formatElapsedTime(mainWindow.call.core.duration) : ""
color: DefaultStyle.grey_0
font {
pixelSize: 22 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
visible: mainWindow.callState === LinphoneEnums.CallState.Connected
|| mainWindow.callState === LinphoneEnums.CallState.StreamsRunning
}
Text {
Layout.leftMargin: 14 * DefaultStyle.dp
id: conferenceDate
text: mainWindow.conferenceInfo ? mainWindow.conferenceInfo.core.getStartEndDateString() : ""
color: DefaultStyle.grey_0
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
capitalization: Font.Capitalize
}
}
} }
} RowLayout {
Rectangle { spacing: 5 * DefaultStyle.dp
visible: mainWindow.call && (mainWindow.callState === LinphoneEnums.CallState.Connected visible: mainWindow.call && mainWindow.call.core.isSecured
|| mainWindow.callState === LinphoneEnums.CallState.StreamsRunning) EffectImage {
Layout.preferredHeight: parent.height Layout.preferredWidth: 15 * DefaultStyle.dp
Layout.preferredWidth: 2 * DefaultStyle.dp Layout.preferredHeight: 15 * DefaultStyle.dp
} colorizationColor: DefaultStyle.info_500_main
Text { imageSource: AppIcons.lockSimple
text: mainWindow.call ? UtilsCpp.formatElapsedTime(mainWindow.call.core.duration) : "" }
color: DefaultStyle.grey_0 Text {
font { text: qsTr("Appel chiffré de bout en bout")
pixelSize: 22 * DefaultStyle.dp color: DefaultStyle.info_500_main
weight: 800 * DefaultStyle.dp font {
} pixelSize: 12 * DefaultStyle.dp
visible: mainWindow.callState === LinphoneEnums.CallState.Connected weight: 400 * DefaultStyle.dp
|| mainWindow.callState === LinphoneEnums.CallState.StreamsRunning }
} }
Text { Item {
text: mainWindow.conferenceInfo ? mainWindow.conferenceInfo.core.getStartEndDateString() : "" Layout.fillWidth: true
color: DefaultStyle.grey_0 }
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
} }
} }
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
} }
RowLayout { Item {
visible: mainWindow.call && (mainWindow.call.core.recording || mainWindow.call.core.remoteRecording) //TODO : network quality display
spacing: 0 }
Text { }
color: DefaultStyle.danger_500main
font.pixelSize: 14 * DefaultStyle.dp Control.Control {
text: mainWindow.call visible: mainWindow.call && (mainWindow.call.core.recording || mainWindow.call.core.remoteRecording)
? mainWindow.call.core.recording width: 563 * DefaultStyle.dp
? qsTr("Vous enregistrez l'appel") height: 45 * DefaultStyle.dp
: qsTr("Votre correspondant enregistre l'appel") anchors.centerIn: parent
: "" leftPadding: 15 * DefaultStyle.dp
} rightPadding: 14 * DefaultStyle.dp
background: Rectangle {
anchors.fill: parent
color: DefaultStyle.grey_500
radius: 10 * DefaultStyle.dp
}
contentItem: RowLayout {
EffectImage { EffectImage {
imageSource: AppIcons.recordFill imageSource: AppIcons.recordFill
colorizationColor: DefaultStyle.danger_500main colorizationColor: DefaultStyle.danger_500main
Layout.preferredWidth: 24 * DefaultStyle.dp Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp Layout.preferredHeight: 24 * DefaultStyle.dp
} }
}
}
Control.Control {
visible: mainWindow.call && mainWindow.call.core.isSecured
anchors.centerIn: parent
topPadding: 8 * DefaultStyle.dp
bottomPadding: 8 * DefaultStyle.dp
leftPadding: 10 * DefaultStyle.dp
rightPadding: 10 * DefaultStyle.dp
width: 269 * DefaultStyle.dp
background: Rectangle {
anchors.fill: parent
border.color: DefaultStyle.info_500_main
radius: 15 * DefaultStyle.dp
}
contentItem: RowLayout {
spacing: 0
Image {
source: AppIcons.trusted
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
sourceSize.width: 24 * DefaultStyle.dp
sourceSize.height: 24 * DefaultStyle.dp
fillMode: Image.PreserveAspectFit
}
Text { Text {
text: "This call is completely secured" color: DefaultStyle.danger_500main
color: DefaultStyle.info_500_main font.pixelSize: 14 * DefaultStyle.dp
font { text: mainWindow.call
pixelSize: 14 * DefaultStyle.dp ? mainWindow.call.core.recording
weight: 400 * DefaultStyle.dp ? mainWindow.conference ? qsTr("Vous enregistrez la réunion") : qsTr("Vous enregistrez l'appel")
} : mainWindow.conference ? qsTr("Un participant enregistre la réunion") : qsTr("Votre correspondant enregistre l'appel")
: ""
}
Button {
visible: mainWindow.call.core.recording
text: qsTr("Arrêter l'enregistrement")
onPressed: mainWindow.call.core.lStopRecording()
} }
} }
} }
@ -379,10 +402,11 @@ AppWindow {
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
spacing: 0 spacing: 23 * DefaultStyle.dp
Layout.rightMargin: 20 * DefaultStyle.dp
Control.StackView { Control.StackView {
id: middleItemStackView id: middleItemStackView
initialItem: mainWindow.call ? inCallItem : waitingRoom initialItem: inCallItem
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
@ -392,7 +416,6 @@ AppWindow {
Layout.fillHeight: true Layout.fillHeight: true
Layout.preferredWidth: 393 * DefaultStyle.dp Layout.preferredWidth: 393 * DefaultStyle.dp
Layout.topMargin: 10 * DefaultStyle.dp Layout.topMargin: 10 * DefaultStyle.dp
Layout.rightMargin: 20 * DefaultStyle.dp // !! Design model is inconsistent
property int currentIndex: 0 property int currentIndex: 0
visible: false visible: false
function replace(id) { function replace(id) {
@ -405,13 +428,19 @@ AppWindow {
} }
Component { Component {
id: contactsListPanel id: contactsListPanel
CallContactsLists { Item {
Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Transfert d'appel") Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Transfert d'appel")
groupCallVisible: false CallContactsLists {
searchBarColor: DefaultStyle.grey_0 anchors.fill: parent
searchBarBorderColor: DefaultStyle.grey_200 anchors.topMargin: 21 * DefaultStyle.dp
onCallButtonPressed: (address) => { anchors.leftMargin: 16 * DefaultStyle.dp
mainWindow.call.core.lTransferCall(address) anchors.rightMargin: 16 * DefaultStyle.dp
groupCallVisible: false
searchBarColor: DefaultStyle.grey_0
searchBarBorderColor: DefaultStyle.grey_200
onCallButtonPressed: (address) => {
mainWindow.call.core.lTransferCall(address)
}
} }
} }
} }
@ -437,16 +466,21 @@ AppWindow {
numericPadButton.visible: false numericPadButton.visible: false
} }
Item { Item {
Layout.fillWidth: true Layout.preferredWidth: parent.width
Layout.preferredHeight: numPad.height Layout.preferredHeight: numPad.height
Layout.topMargin: 10 * DefaultStyle.dp Layout.topMargin: 10 * DefaultStyle.dp
NumericPad { NumericPad {
id: numPad id: numPad
width: parent.width width: parent.width
visible: parent.visible
closeButtonVisible: false closeButtonVisible: false
roundedBottom: true
visible: parent.visible
leftPadding: 40 * DefaultStyle.dp
rightPadding: 40 * DefaultStyle.dp
topPadding: 41 * DefaultStyle.dp
bottomPadding: 18 * DefaultStyle.dp
onLaunchCall: { onLaunchCall: {
UtilsCpp.createCall(dialerTextInput.text + "@sip.linphone.org") UtilsCpp.createCall(dialerTextInput.text)
} }
} }
} }
@ -454,62 +488,69 @@ AppWindow {
} }
Component { Component {
id: changeLayoutPanel id: changeLayoutPanel
ColumnLayout { Item {
Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Modifier la disposition") Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Modifier la disposition")
spacing: 12 * DefaultStyle.dp ColumnLayout {
Text { anchors.fill: parent
Layout.fillWidth: true anchors.topMargin: 16 * DefaultStyle.dp
text: qsTr("La disposition choisie sera enregistrée pour vos prochaines réunions") anchors.bottomMargin: 16 * DefaultStyle.dp
font.pixelSize: 14 * DefaultStyle.dp anchors.leftMargin: 17 * DefaultStyle.dp
color: DefaultStyle.main2_500main anchors.rightMargin: 17 * DefaultStyle.dp
} spacing: 12 * DefaultStyle.dp
RoundedBackgroundControl { Text {
Layout.fillWidth: true Layout.fillWidth: true
contentItem: ColumnLayout { text: qsTr("La disposition choisie sera enregistrée pour vos prochaines réunions")
spacing: 0 font.pixelSize: 14 * DefaultStyle.dp
Repeater { color: DefaultStyle.main2_500main
model: [ }
{text: qsTr("Mosaïque"), imgUrl: AppIcons.squaresFour}, RoundedBackgroundControl {
{text: qsTr("Intervenant actif"), imgUrl: AppIcons.pip}, Layout.fillWidth: true
{text: qsTr("Audio seulement"), imgUrl: AppIcons.waveform} contentItem: ColumnLayout {
] spacing: 0
RadioButton { Repeater {
id: radiobutton model: [
checkOnClick: false {text: qsTr("Mosaïque"), imgUrl: AppIcons.squaresFour},
color: DefaultStyle.main1_500_main {text: qsTr("Intervenant actif"), imgUrl: AppIcons.pip},
indicatorSize: 20 * DefaultStyle.dp {text: qsTr("Audio seulement"), imgUrl: AppIcons.waveform}
leftPadding: indicator.width + spacing ]
spacing: 8 * DefaultStyle.dp RadioButton {
checkable: false // Qt Documentation is wrong: It is true by default. We don't want to change the checked state if the layout change is not effective. id: radiobutton
checked: index == 0 checkOnClick: false
? mainWindow.conferenceLayout === LinphoneEnums.ConferenceLayout.Grid color: DefaultStyle.main1_500_main
: index == 1 indicatorSize: 20 * DefaultStyle.dp
? mainWindow.conferenceLayout === LinphoneEnums.ConferenceLayout.ActiveSpeaker leftPadding: indicator.width + spacing
: mainWindow.conferenceLayout === LinphoneEnums.ConferenceLayout.AudioOnly spacing: 8 * DefaultStyle.dp
onClicked: mainWindow.changeLayout(index) checkable: false // Qt Documentation is wrong: It is true by default. We don't want to change the checked state if the layout change is not effective.
checked: index == 0
? mainWindow.conferenceLayout === LinphoneEnums.ConferenceLayout.Grid
: index == 1
? mainWindow.conferenceLayout === LinphoneEnums.ConferenceLayout.ActiveSpeaker
: mainWindow.conferenceLayout === LinphoneEnums.ConferenceLayout.AudioOnly
onClicked: mainWindow.changeLayout(index)
contentItem: RowLayout { contentItem: RowLayout {
spacing: 5 * DefaultStyle.dp spacing: 5 * DefaultStyle.dp
EffectImage { EffectImage {
id: radioButtonImg id: radioButtonImg
Layout.preferredWidth: 32 * DefaultStyle.dp Layout.preferredWidth: 32 * DefaultStyle.dp
Layout.preferredHeight: 32 * DefaultStyle.dp Layout.preferredHeight: 32 * DefaultStyle.dp
imageSource: modelData.imgUrl imageSource: modelData.imgUrl
colorizationColor: DefaultStyle.main2_500main colorizationColor: DefaultStyle.main2_500main
} }
Text { Text {
text: modelData.text text: modelData.text
color: DefaultStyle.main2_500main color: DefaultStyle.main2_500main
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
font.pixelSize: 14 * DefaultStyle.dp font.pixelSize: 14 * DefaultStyle.dp
Layout.fillWidth: true Layout.fillWidth: true
}
} }
} }
} }
} }
} }
Item {Layout.fillHeight: true}
} }
Item {Layout.fillHeight: true}
} }
} }
Component { Component {
@ -521,10 +562,15 @@ AppWindow {
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumHeight: rightPanel.height Layout.maximumHeight: rightPanel.height
visible: callList.contentHeight > 0 visible: callList.contentHeight > 0
leftPadding: 17 * DefaultStyle.dp leftPadding: 16 * DefaultStyle.dp
rightPadding: 17 * DefaultStyle.dp rightPadding: 16 * DefaultStyle.dp
topPadding: 16 * DefaultStyle.dp topPadding: 15 * DefaultStyle.dp
bottomPadding: 16 * DefaultStyle.dp bottomPadding: 16 * DefaultStyle.dp
Layout.topMargin: 15 * DefaultStyle.dp
Layout.bottomMargin: 16 * DefaultStyle.dp
Layout.leftMargin: 16 * DefaultStyle.dp
Layout.rightMargin: 16 * DefaultStyle.dp
contentItem: ListView { contentItem: ListView {
id: callList id: callList
@ -565,9 +611,11 @@ AppWindow {
Text { Text {
id: callStateText id: callStateText
Layout.rightMargin: 2 * DefaultStyle.dp Layout.rightMargin: 2 * DefaultStyle.dp
text: modelData.core.state === LinphoneEnums.CallState.Paused property string type: modelData.core.isConference ? qsTr('Réunion') : qsTr('Appel')
text: modelData.core.state === LinphoneEnums.CallState.Paused
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote || modelData.core.state === LinphoneEnums.CallState.PausedByRemote
? qsTr("Appel en pause") : qsTr("Appel en cours") ? type + qsTr(" en pause")
: type + qsTr(" en cours")
} }
PopupButton { PopupButton {
id: listCallOptionsButton id: listCallOptionsButton
@ -579,7 +627,7 @@ AppWindow {
Button { Button {
background: Item {} background: Item {}
contentItem: RowLayout { contentItem: RowLayout {
spacing: 0 spacing: 5 * DefaultStyle.dp
Image { Image {
source: modelData.core.state === LinphoneEnums.CallState.Paused source: modelData.core.state === LinphoneEnums.CallState.Paused
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote || modelData.core.state === LinphoneEnums.CallState.PausedByRemote
@ -595,11 +643,6 @@ AppWindow {
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote || modelData.core.state === LinphoneEnums.CallState.PausedByRemote
? qsTr("Reprendre l'appel") : qsTr("Mettre en pause") ? qsTr("Reprendre l'appel") : qsTr("Mettre en pause")
color: DefaultStyle.main2_500main color: DefaultStyle.main2_500main
Layout.preferredWidth: metrics.width
}
TextMetrics {
id: metrics
text: qsTr("Reprendre l'appel")
} }
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
@ -610,7 +653,7 @@ AppWindow {
Button { Button {
background: Item {} background: Item {}
contentItem: RowLayout { contentItem: RowLayout {
spacing: 0 spacing: 5 * DefaultStyle.dp
EffectImage { EffectImage {
imageSource: AppIcons.endCall imageSource: AppIcons.endCall
colorizationColor: DefaultStyle.danger_500main colorizationColor: DefaultStyle.danger_500main
@ -640,103 +683,120 @@ AppWindow {
} }
Component { Component {
id: settingsPanel id: settingsPanel
InCallSettingsPanel { Item {
Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Paramètres") Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Paramètres")
call: mainWindow.call InCallSettingsPanel {
anchors.fill: parent
call: mainWindow.call
anchors.topMargin: 16 * DefaultStyle.dp
anchors.bottomMargin: 16 * DefaultStyle.dp
anchors.leftMargin: 17 * DefaultStyle.dp
anchors.rightMargin: 17 * DefaultStyle.dp
}
} }
} }
Component { Component {
id: screencastPanel id: screencastPanel
ScreencastPanel { Item {
call: mainWindow.call
Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Partage de votre écran") Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Partage de votre écran")
ScreencastPanel {
anchors.topMargin: 16 * DefaultStyle.dp
anchors.bottomMargin: 16 * DefaultStyle.dp
anchors.leftMargin: 17 * DefaultStyle.dp
anchors.rightMargin: 17 * DefaultStyle.dp
call: mainWindow.call
}
} }
} }
Component { Component {
id: participantListPanel id: participantListPanel
Control.StackView { Item {
id: participantsStack Control.StackView {
initialItem: participantListComp id: participantsStack
// Control.StackView.onActivated: rightPanel.headerTitleText = qsTr("Participants (%1)").arg(participantList.count) anchors.fill: parent
onCurrentItemChanged: rightPanel.headerStack.currentIndex = currentItem.Control.StackView.index anchors.bottomMargin: 16 * DefaultStyle.dp
property list<string> selectedParticipants anchors.leftMargin: 17 * DefaultStyle.dp
signal participantAdded() anchors.rightMargin: 17 * DefaultStyle.dp
initialItem: participantListComp
onCurrentItemChanged: rightPanel.headerStack.currentIndex = currentItem.Control.StackView.index
property list<string> selectedParticipants
signal participantAdded()
Connections { Connections {
target: rightPanel target: rightPanel
onReturnRequested: participantsStack.pop() onReturnRequested: participantsStack.pop()
} }
Component { Component {
id: participantListComp id: participantListComp
ParticipantListView { ParticipantListView {
id: participantList id: participantList
Component { Component {
id: headerbutton id: headerbutton
PopupButton { PopupButton {
popup.contentItem: Button { popup.contentItem: Button {
background: Item{} background: Item{}
contentItem: RowLayout { contentItem: RowLayout {
spacing: 0 spacing: 0
EffectImage { EffectImage {
colorizationColor: DefaultStyle.main2_600 colorizationColor: DefaultStyle.main2_600
imageSource: AppIcons.shareNetwork imageSource: AppIcons.shareNetwork
Layout.preferredWidth: 24 * DefaultStyle.dp Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp Layout.preferredHeight: 24 * DefaultStyle.dp
}
Text {
text: qsTr("Partager le lien de la réunion")
font.pixelSize: 14 * DefaultStyle.dp
}
} }
Text { onClicked: {
text: qsTr("Partager le lien de la réunion") UtilsCpp.copyToClipboard(mainWindow.conference.core.uri)
font.pixelSize: 14 * DefaultStyle.dp showInformationPopup(qsTr("Copié"), qsTr("Le lien de la réunion a été copié dans le presse-papier"), true)
} }
} }
onClicked: {
mainItem.shareInvitation()
}
} }
} }
} Control.StackView.onActivated: {
Control.StackView.onActivated: { rightPanel.customHeaderButtons = headerbutton.createObject(rightPanel)
rightPanel.customHeaderButtons = headerbutton.createObject(rightPanel)
}
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: {
if (participantsStack.currentItem == participantList) rightPanel.headerTitleText = qsTr("Participants (%1)").arg(participantList.count)
} }
} call: mainWindow.call
Connections { onAddParticipantRequested: participantsStack.push(addParticipantComp)
target: rightPanel onCountChanged: if (participantsStack.Control.StackView.status === Control.StackView.Active && participantsStack.currentItem == participantListComp) {
onValidateRequested: { rightPanel.headerTitleText = qsTr("Participants (%1)").arg(count)
participantList.model.addAddresses(participantsStack.selectedParticipants) }
participantsStack.pop() Connections {
participantsStack.participantAdded() target: participantsStack
onCurrentItemChanged: {
if (participantsStack.currentItem == participantList) rightPanel.headerTitleText = qsTr("Participants (%1)").arg(participantList.count)
}
}
Connections {
target: rightPanel
onValidateRequested: {
participantList.model.addAddresses(participantsStack.selectedParticipants)
participantsStack.pop()
participantsStack.participantAdded()
}
} }
} }
} }
} Component {
Component { id: addParticipantComp
id: addParticipantComp AddParticipantsLayout {
AddParticipantsLayout { id: addParticipantLayout
id: addParticipantLayout searchBarColor: DefaultStyle.grey_0
searchBarColor: DefaultStyle.grey_0 searchBarBorderColor: DefaultStyle.grey_200
searchBarBorderColor: DefaultStyle.grey_200 onSelectedParticipantsCountChanged: {
onSelectedParticipantsCountChanged: { rightPanel.headerSubtitleText = qsTr("%1 participant%2 sélectionné%2").arg(selectedParticipantsCount).arg(selectedParticipantsCount > 1 ? "s" : "")
if (participantsStack.Control.StackView.status === Control.StackView.Active && Control.StackView.visible) { participantsStack.selectedParticipants = selectedParticipants
rightPanel.headerSubtitleText = qsTr("%1 participant%2 sélectionné").arg(selectedParticipants.length).arg(selectedParticipants.length > 1 ? "s" : "")
} }
participantsStack.selectedParticipants = selectedParticipants Connections {
} target: participantsStack
Connections { onCurrentItemChanged: {
target: participantsStack if (participantsStack.currentItem == addParticipantLayout) {
onCurrentItemChanged: { rightPanel.headerTitleText = qsTr("Ajouter des participants")
if (participantsStack.currentItem == addParticipantLayout) { rightPanel.headerSubtitleText = qsTr("%1 participant%2 sélectionné%2").arg(addParticipantLayout.selectedParticipants.length).arg(addParticipantLayout.selectedParticipants.length > 1 ? "s" : "")
rightPanel.headerTitleText = qsTr("Ajouter des participants") }
rightPanel.headerSubtitleText = qsTr("%1 participant%2 sélectionné%2").arg(addParticipantLayout.selectedParticipants.length).arg(addParticipantLayout.selectedParticipants.length > 1 ? "s" : "")
} }
} }
} }
@ -750,7 +810,6 @@ AppWindow {
WaitingRoom { WaitingRoom {
id: waitingRoomIn id: waitingRoomIn
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
conferenceInfo: mainWindow.conferenceInfo
onSettingsButtonCheckedChanged: { onSettingsButtonCheckedChanged: {
if (settingsButtonChecked) { if (settingsButtonChecked) {
rightPanel.visible = true rightPanel.visible = true
@ -759,16 +818,46 @@ AppWindow {
rightPanel.visible = false rightPanel.visible = false
} }
} }
Binding {
target: callStatusIcon
when: middleItemStackView.currentItem === waitingRoomIn
property: "imageSource"
value: AppIcons.usersThree
restoreMode: Binding.RestoreBindingOrValue
}
Binding {
target: callStatusText
when: middleItemStackView.currentItem === waitingRoomIn
property: "text"
value: waitingRoomIn.conferenceInfo.core.subject
restoreMode: Binding.RestoreBindingOrValue
}
Binding {
target: conferenceDate
when: middleItemStackView.currentItem === waitingRoomIn
property: "text"
value: waitingRoomIn.conferenceInfo.core.startEndDateString
}
Connections { Connections {
target: rightPanel target: rightPanel
onVisibleChanged: if (!visible) waitingRoomIn.settingsButtonChecked = false onVisibleChanged: if (!visible) waitingRoomIn.settingsButtonChecked = false
} }
onJoinConfRequested: mainWindow.joinConference({'microEnabled':microEnabled, 'localVideoEnabled':localVideoEnabled}) Connections {
target:mainWindow
onSetUpConferenceRequested: (conferenceInfo) => {
waitingRoomIn.conferenceInfo = conferenceInfo
}
}
onJoinConfRequested: (uri) => {
mainWindow.joinConference(uri, {'microEnabled':microEnabled, 'localVideoEnabled':localVideoEnabled})
}
onCancelJoiningRequested: mainWindow.cancelJoinConference()
} }
} }
Component { Component {
id: inCallItem id: inCallItem
Item { Item {
property string objectName: "inCallItem"
CallLayout{ CallLayout{
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: 20 * DefaultStyle.dp anchors.leftMargin: 20 * DefaultStyle.dp
@ -776,7 +865,6 @@ AppWindow {
anchors.topMargin: 10 * DefaultStyle.dp anchors.topMargin: 10 * DefaultStyle.dp
call: mainWindow.call call: mainWindow.call
callTerminatedByUser: mainWindow.callTerminatedByUser callTerminatedByUser: mainWindow.callTerminatedByUser
onShareInvitationRequested: mainWindow.shareInvitation()
} }
} }
} }
@ -784,7 +872,7 @@ AppWindow {
id: bottomButtonsLayout id: bottomButtonsLayout
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
spacing: 58 * DefaultStyle.dp spacing: 58 * DefaultStyle.dp
visible: mainWindow.call && !mainWindow.conferenceInfo visible: middleItemStackView.currentItem.objectName == "inCallItem"
function refreshLayout() { function refreshLayout() {
if (mainWindow.callState === LinphoneEnums.CallState.Connected || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning) { if (mainWindow.callState === LinphoneEnums.CallState.Connected || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning) {
@ -1058,6 +1146,7 @@ AppWindow {
icon.source: AppIcons.recordFill icon.source: AppIcons.recordFill
icon.width: 32 * DefaultStyle.dp icon.width: 32 * DefaultStyle.dp
icon.height: 32 * DefaultStyle.dp icon.height: 32 * DefaultStyle.dp
checked: mainWindow.call && mainWindow.call.core.recording
contentImageColor: down contentImageColor: down
? DefaultStyle.main1_500_main ? DefaultStyle.main1_500_main
:mainWindow.call && mainWindow.call.core.recording :mainWindow.call && mainWindow.call.core.recording
@ -1070,7 +1159,7 @@ AppWindow {
? DefaultStyle.danger_500main ? DefaultStyle.danger_500main
: DefaultStyle.main2_500main : DefaultStyle.main2_500main
Layout.fillWidth: true Layout.fillWidth: true
onCheckedChanged: { onToggled: {
if (mainWindow.call) if (mainWindow.call)
if (mainWindow.call.core.recording) mainWindow.call.core.lStopRecording() if (mainWindow.call.core.recording) mainWindow.call.core.lStopRecording()
else mainWindow.call.core.lStartRecording() else mainWindow.call.core.lStartRecording()

View file

@ -41,8 +41,8 @@ Control.Button {
? inversedColors ? inversedColors
? mainItem.pressed ? mainItem.pressed
? DefaultStyle.grey_100 ? DefaultStyle.grey_100
: DefaultStyle.grey_0 : mainItem.borderColor
: mainItem.pressed : mainItem.pressed
? mainItem.pressedColor ? mainItem.pressedColor
: mainItem.color : mainItem.color
: mainItem.disabledColor : mainItem.disabledColor

View file

@ -125,7 +125,6 @@ Item {
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumWidth: mainItem.width Layout.maximumWidth: mainItem.width
Layout.rightMargin: 39 * DefaultStyle.dp
color: mainItem.searchBarColor color: mainItem.searchBarColor
borderColor: mainItem.searchBarBorderColor borderColor: mainItem.searchBarBorderColor
placeholderText: qsTr("Rechercher un contact") placeholderText: qsTr("Rechercher un contact")

View file

@ -42,6 +42,7 @@ ColumnLayout {
} }
Text { Text {
text: qsTr("Haut-parleurs") text: qsTr("Haut-parleurs")
font.pixelSize: 14 * DefaultStyle.dp
Layout.fillWidth: true Layout.fillWidth: true
} }
} }
@ -80,6 +81,7 @@ ColumnLayout {
} }
Text { Text {
text: qsTr("Microphone") text: qsTr("Microphone")
font.pixelSize: 14 * DefaultStyle.dp
Layout.fillWidth: true Layout.fillWidth: true
} }
} }
@ -153,6 +155,7 @@ ColumnLayout {
} }
Text { Text {
text: qsTr("Caméra") text: qsTr("Caméra")
font.pixelSize: 14 * DefaultStyle.dp
Layout.fillWidth: true Layout.fillWidth: true
} }
} }

View file

@ -18,9 +18,7 @@ Control.Page {
signal validateRequested() signal validateRequested()
topPadding: 16 * DefaultStyle.dp topPadding: 16 * DefaultStyle.dp
bottomPadding: 16 * DefaultStyle.dp // bottomPadding: 16 * DefaultStyle.dp
leftPadding: 17 * DefaultStyle.dp
rightPadding: 17 * DefaultStyle.dp
background: Rectangle { background: Rectangle {
width: mainItem.width width: mainItem.width
@ -135,7 +133,5 @@ Control.Page {
} }
contentItem: Control.StackView { contentItem: Control.StackView {
id: contentStackView id: contentStackView
// width: parent.width
// height: parent.height
} }
} }

View file

@ -11,7 +11,8 @@ RowLayout {
property bool microEnabled: true property bool microEnabled: true
property bool settingsButtonChecked: settingsButton.checked property bool settingsButtonChecked: settingsButton.checked
property ConferenceInfoGui conferenceInfo property ConferenceInfoGui conferenceInfo
signal joinConfRequested() signal joinConfRequested(string uri)
signal cancelJoiningRequested()
RowLayout { RowLayout {
Layout.fillWidth: false Layout.fillWidth: false
Layout.fillHeight: false Layout.fillHeight: false
@ -114,17 +115,31 @@ RowLayout {
} }
} }
} }
Button { ColumnLayout {
Layout.preferredWidth: 292 * DefaultStyle.dp spacing: 5 * DefaultStyle.dp
leftPadding: 20 * DefaultStyle.dp Button {
rightPadding: 20 * DefaultStyle.dp Layout.preferredWidth: 292 * DefaultStyle.dp
topPadding: 11 * DefaultStyle.dp leftPadding: 20 * DefaultStyle.dp
bottomPadding: 11 * DefaultStyle.dp rightPadding: 20 * DefaultStyle.dp
text: qsTr("Join") topPadding: 11 * DefaultStyle.dp
onClicked: { bottomPadding: 11 * DefaultStyle.dp
settingsButton.checked = false text: qsTr("Join")
stackLayout.currentIndex = 1 onClicked: {
mainItem.joinConfRequested() settingsButton.checked = false
stackLayout.currentIndex = 1
mainItem.joinConfRequested(mainItem.conferenceInfo.core.uri)
}
}
Button {
Layout.preferredWidth: 292 * DefaultStyle.dp
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
bottomPadding: 11 * DefaultStyle.dp
inversedColors: true
text: qsTr("Cancel")
onClicked: {
mainItem.cancelJoiningRequested()
}
} }
} }
} }

View file

@ -10,34 +10,37 @@ Control.Popup {
signal launchCall() signal launchCall()
signal wipe() signal wipe()
property bool closeButtonVisible: true property bool closeButtonVisible: true
property bool roundedBottom: false
closePolicy: Control.Popup.CloseOnEscape closePolicy: Control.Popup.CloseOnEscape
leftPadding: 72 * DefaultStyle.dp leftPadding: 72 * DefaultStyle.dp
rightPadding: 72 * DefaultStyle.dp rightPadding: 72 * DefaultStyle.dp
topPadding: 41 * DefaultStyle.dp topPadding: 41 * DefaultStyle.dp
bottomPadding: 18 * DefaultStyle.dp bottomPadding: 18 * DefaultStyle.dp
// topPadding: closeButton.height + 4 * DefaultStyle.dp
background: Item { background: Item {
anchors.fill: parent anchors.fill: parent
Rectangle { Rectangle {
id: numPadBackground id: numPadBackground
anchors.fill: parent width: parent.width
height: parent.height
color: DefaultStyle.grey_100 color: DefaultStyle.grey_100
radius: 20 * DefaultStyle.dp radius: 20 * DefaultStyle.dp
} }
MultiEffect { MultiEffect {
id: effect id: effect
anchors.fill: parent anchors.fill: numPadBackground
source: numPadBackground source: numPadBackground
shadowEnabled: true shadowEnabled: true
shadowColor: DefaultStyle.grey_1000 shadowColor: DefaultStyle.grey_1000
shadowOpacity: 0.1 shadowOpacity: 0.1
shadowBlur: 1 shadowBlur: 1
z: -1
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: parent.height / 2 height: parent.height / 2
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
color: DefaultStyle.grey_100 color: DefaultStyle.grey_100
visible: !mainItem.roundedBottom
} }
Button { Button {
id: closeButton id: closeButton

View file

@ -13,36 +13,116 @@ Item{
id: mainItem id: mainItem
property alias call: allDevices.currentCall property alias call: allDevices.currentCall
property ConferenceGui conference: call && call.core.conference || null property ConferenceGui conference: call && call.core.conference || null
property int participantDeviceCount: allDevices.count
onParticipantDeviceCountChanged: {
setUpMainItem()
}
property var callState: call && call.core.state || undefined property var callState: call && call.core.state || undefined
onCallStateChanged: if (callState === LinphoneEnums.CallState.End || callState === LinphoneEnums.CallState.Released) preview.visible = false
property string localAddress: call && call.conference property string localAddress: call && call.conference
? call.conference.core.me.core.sipAddress ? call.conference.core.me.core.sipAddress
: call.core.localAddress : call.core.localAddress
|| "" || ""
onLocalAddressChanged: console.log("======== local addr changed", localAddress)
// currently speaking address (for hiding in list view)
property string activeSpeakerAddress
property ParticipantDeviceProxy participantDevices : ParticipantDeviceProxy { property ParticipantDeviceProxy participantDevices : ParticipantDeviceProxy {
id: allDevices id: allDevices
qmlName: "AS" qmlName: "AS"
onCountChanged: console.log("Device count changed : " +count) onCountChanged: console.log("Device count changed : " +count)
Component.onCompleted: console.log("Loaded : " +allDevices) Component.onCompleted: console.log("Loaded : " +allDevices)
} }
onCallStateChanged: if (callState === LinphoneEnums.CallState.End || callState === LinphoneEnums.CallState.Released) preview.visible = false
Component.onCompleted: setUpMainItem()
onVisibleChanged: if (visible) setUpMainItem()
function setUpMainItem() {
if (mainItem.conference && mainItem.participantDeviceCount <= 1) {
mainStackView.replace(waitingForOthersComponent)
} else {
mainStackView.replace(activeSpeakerComp)
}
}
RowLayout{ RowLayout{
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: 10 * DefaultStyle.dp anchors.rightMargin: 10 * DefaultStyle.dp
spacing: 16 * DefaultStyle.dp spacing: 16 * DefaultStyle.dp
Sticker { Control.StackView {
id: activeSpeakerSticker id: mainStackView
previewEnabled: false // initialItem: waitingForOthersComponent
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
call: mainItem.call }
participantDevice: mainItem.conference && mainItem.conference.core.activeSpeaker Component {
property var address: participantDevice && participantDevice.core.address id: waitingForOthersComponent
videoEnabled: (participantDevice && participantDevice.core.videoEnabled) || (!participantDevice && call && call.core.remoteVideoEnabled) Rectangle {
qmlName: 'AS' color: DefaultStyle.grey_600
displayPresence: false radius: 15 * DefaultStyle.dp
ColumnLayout {
anchors.centerIn: parent
spacing: 22 * DefaultStyle.dp
width: waitText.implicitWidth
Text {
id: waitText
text: qsTr("Waiting for other participants...")
Layout.preferredHeight: 67 * DefaultStyle.dp
Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
color: DefaultStyle.grey_0
font {
pixelSize: 30 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
}
Item {
Layout.fillWidth: true
Button {
color: "transparent"
borderColor: DefaultStyle.main2_400
pressedColor: DefaultStyle.main2_500main
icon.source: AppIcons.shareNetwork
contentImageColor: DefaultStyle.main2_400
text: qsTr("Share invitation")
topPadding: 11 * DefaultStyle.dp
bottomPadding: 11 * DefaultStyle.dp
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
anchors.centerIn: parent
textColor: DefaultStyle.main2_400
onClicked: {
if (mainItem.conference) {
UtilsCpp.copyToClipboard(mainItem.call.core.peerAddress)
showInformationPopup(qsTr("Copié"), qsTr("Le lien de la réunion a été copié dans le presse-papier"), true)
}
}
}
}
}
}
}
Component {
id: activeSpeakerComp
Sticker {
id: activeSpeakerSticker
previewEnabled: false
call: mainItem.call
width: parent.width
height: parent.height
participantDevice: mainItem.conference && mainItem.conference.core.activeSpeaker
property var address: participantDevice && participantDevice.core.address
videoEnabled: (participantDevice && participantDevice.core.videoEnabled) || (!participantDevice && call && call.core.remoteVideoEnabled)
qmlName: 'AS'
displayPresence: false
Binding {
target: mainItem
property: "activeSpeakerAddress"
value: activeSpeakerSticker.address
when: true
}
}
} }
ListView{ ListView{
Layout.fillHeight: true Layout.fillHeight: true
@ -56,7 +136,7 @@ Item{
clip: true clip: true
delegate: Item{ // Spacing workaround delegate: Item{ // Spacing workaround
visible: $modelData && mainItem.callState != LinphoneEnums.CallState.End && mainItem.callState != LinphoneEnums.CallState.Released visible: $modelData && mainItem.callState != LinphoneEnums.CallState.End && mainItem.callState != LinphoneEnums.CallState.Released
&& $modelData.core.address != activeSpeakerSticker.address || false && $modelData.core.address != activeSpeakerAddress || false
height: visible ? (180 + 15) * DefaultStyle.dp : 0 height: visible ? (180 + 15) * DefaultStyle.dp : 0
width: 300 * DefaultStyle.dp width: 300 * DefaultStyle.dp
Sticker { Sticker {

View file

@ -16,7 +16,10 @@ Item {
property bool callTerminatedByUser: false property bool callTerminatedByUser: false
readonly property var callState: call && call.core.state || undefined readonly property var callState: call && call.core.state || undefined
property int conferenceLayout: call && call.core.conferenceVideoLayout || 0 property int conferenceLayout: call && call.core.conferenceVideoLayout || 0
property int participantDeviceCount: conference ? conference.core.participantDeviceCount : -1 // property int participantDeviceCount: conference ? conference.core.participantDeviceCount : -1
// onParticipantDeviceCountChanged: {
// setConferenceLayout()
// }
Component.onCompleted: setConferenceLayout() Component.onCompleted: setConferenceLayout()
onConferenceLayoutChanged: { onConferenceLayoutChanged: {
console.log("CallLayout change : " +conferenceLayout) console.log("CallLayout change : " +conferenceLayout)
@ -25,16 +28,14 @@ Item {
onCallStateChanged: { onCallStateChanged: {
if( callState === LinphoneEnums.CallState.Error) { if( callState === LinphoneEnums.CallState.Error) {
centerLayout.currentIndex = 1 centerLayout.currentIndex = 1
} else if( callState === LinphoneEnums.CallState.End) { }
callTerminatedText.visible = true // else if( callState === LinphoneEnums.CallState.End) {
} // callTerminatedText.visible = true
// }
} }
// onCallChanged: callTerminatedText.visible = false
signal shareInvitationRequested()
function setConferenceLayout() { function setConferenceLayout() {
if (mainItem.participantDeviceCount < 2 ) {
return
}
callLayout.sourceComponent = undefined // unload old view before opening the new view to avoid conflicts in Video UI. callLayout.sourceComponent = undefined // unload old view before opening the new view to avoid conflicts in Video UI.
callLayout.sourceComponent = mainItem.conferenceLayout == LinphoneEnums.ConferenceLayout.ActiveSpeaker callLayout.sourceComponent = mainItem.conferenceLayout == LinphoneEnums.ConferenceLayout.ActiveSpeaker
? activeSpeakerComponent ? activeSpeakerComponent
@ -47,7 +48,7 @@ Item {
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: 25 * DefaultStyle.dp anchors.topMargin: 25 * DefaultStyle.dp
z: 1 z: 1
visible: false visible: callState === LinphoneEnums.CallState.End
text: mainItem.conference text: mainItem.conference
? qsTr("Vous avez quitté la conférence") ? qsTr("Vous avez quitté la conférence")
: mainItem.callTerminatedByUser : mainItem.callTerminatedByUser
@ -68,7 +69,7 @@ Item {
id: callLayout id: callLayout
Layout.Layout.fillWidth: true Layout.Layout.fillWidth: true
Layout.Layout.fillHeight: true Layout.Layout.fillHeight: true
sourceComponent: mainItem.conference && mainItem.participantDeviceCount < 2 sourceComponent: mainItem.participantDeviceCount === 0
? waitingForOthersComponent ? waitingForOthersComponent
: activeSpeakerComponent : activeSpeakerComponent
} }
@ -101,50 +102,6 @@ Item {
call: mainItem.call call: mainItem.call
} }
} }
Component {
id: waitingForOthersComponent
Rectangle {
color: DefaultStyle.grey_600
radius: 15 * DefaultStyle.dp
Layout.Layout.fillWidth: true
Layout.Layout.fillHeight: true
Layout.ColumnLayout {
id: waitingForOthersLayout
anchors.centerIn: parent
spacing: 22 * DefaultStyle.dp
Text {
text: qsTr("Waiting for other participants...")
Layout.Layout.preferredHeight: 67 * DefaultStyle.dp
Layout.Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
color: DefaultStyle.grey_0
font {
pixelSize: 30 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
}
Button {
color: "transparent"
borderColor: DefaultStyle.main2_400
pressedColor: DefaultStyle.main2_500main
icon.source: AppIcons.shareNetwork
contentImageColor: DefaultStyle.main2_400
text: qsTr("Share invitation")
topPadding: 11 * DefaultStyle.dp
bottomPadding: 11 * DefaultStyle.dp
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
Layout.Layout.alignment: Qt.AlignHCenter
textColor: DefaultStyle.main2_400
onClicked: {
if (mainItem.conference) {
mainItem.shareInvitationRequested()
}
}
}
}
}
}
} }
// TODO : waitingForParticipant // TODO : waitingForParticipant
// ColumnLayout { // ColumnLayout {

View file

@ -23,10 +23,10 @@ Mosaic {
Component.onCompleted: console.log("Loaded : " +allDevices + " = " +allDevices.count) Component.onCompleted: console.log("Loaded : " +allDevices + " = " +allDevices.count)
} }
property AccountProxy accounts: AccountProxy{id: accountProxy} property AccountProxy accounts: AccountProxy{id: accountProxy}
model: grid.call.core.isConference ? participantDevices: [0,1] model: grid.call && grid.call.core.isConference ? participantDevices: [0,1]
delegate: Item{ delegate: Item{
id: avatarCell id: avatarCell
property ParticipantDeviceGui currentDevice: index >= 0 && grid.call.core.isConference ? $modelData : null property ParticipantDeviceGui currentDevice: index >= 0 && grid.call && grid.call.core.isConference ? $modelData : null
onCurrentDeviceChanged: { onCurrentDeviceChanged: {
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) 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)
} }
@ -39,7 +39,7 @@ Mosaic {
visible: mainItem.callState != LinphoneEnums.CallState.End && mainItem.callState != LinphoneEnums.CallState.Released visible: mainItem.callState != LinphoneEnums.CallState.End && mainItem.callState != LinphoneEnums.CallState.Released
anchors.fill: parent anchors.fill: parent
qmlName: 'G_'+index qmlName: 'G_'+index
call: !grid.call.core.isConference ? grid.call : null call: grid.call && !grid.call.core.isConference ? grid.call : null
account: index == 0 ? accountProxy.findAccountByAddress(mainItem.localAddress) : null account: index == 0 ? accountProxy.findAccountByAddress(mainItem.localAddress) : null
displayAll: false displayAll: false
bigBottomAddress: true bigBottomAddress: true

View file

@ -10,6 +10,8 @@ ColumnLayout {
spacing: 30 * DefaultStyle.dp spacing: 30 * DefaultStyle.dp
property FriendGui contact property FriendGui contact
property ConferenceInfoGui conferenceInfo
property bool isConference: conferenceInfo != undefined && conferenceInfo != null
property string contactAddress: contact && contact.core.defaultAddress || "" property string contactAddress: contact && contact.core.defaultAddress || ""
property string contactName: contact && contact.core.displayName || "" property string contactName: contact && contact.core.displayName || ""
@ -31,6 +33,7 @@ ColumnLayout {
bottomPadding: 16 * DefaultStyle.dp bottomPadding: 16 * DefaultStyle.dp
leftPadding: 16 * DefaultStyle.dp leftPadding: 16 * DefaultStyle.dp
rightPadding: 16 * DefaultStyle.dp rightPadding: 16 * DefaultStyle.dp
contentImageColor: DefaultStyle.main2_600
background: Rectangle { background: Rectangle {
anchors.fill: parent anchors.fill: parent
radius: 40 * DefaultStyle.dp radius: 40 * DefaultStyle.dp
@ -58,7 +61,9 @@ ColumnLayout {
width: 100 * DefaultStyle.dp width: 100 * DefaultStyle.dp
height: 100 * DefaultStyle.dp height: 100 * DefaultStyle.dp
contact: mainItem.contact || null contact: mainItem.contact || null
address: mainItem.contactAddress || mainItem.contactName address: mainItem.conferenceInfo
? mainItem.conferenceInfo.core.subject
: mainItem.contactAddress || mainItem.contactName
} }
Item { Item {
id: rightButton id: rightButton
@ -118,7 +123,23 @@ ColumnLayout {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: mainItem.implicitWidth Layout.preferredWidth: mainItem.implicitWidth
Layout.preferredHeight: childrenRect.height Layout.preferredHeight: childrenRect.height
Button {
visible: mainItem.isConference
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Rejoindre la réunion")
color: DefaultStyle.main2_200
pressedColor: DefaultStyle.main2_400
textColor: DefaultStyle.main2_600
onClicked: {
if (mainItem.conferenceInfo) {
var callsWindow = UtilsCpp.getCallsWindow()
callsWindow.setupConference(mainItem.conferenceInfo)
callsWindow.show()
}
}
}
LabelButton { LabelButton {
visible: !mainItem.isConference
anchors.left: parent.left anchors.left: parent.left
width: 56 * DefaultStyle.dp width: 56 * DefaultStyle.dp
height: 56 * DefaultStyle.dp height: 56 * DefaultStyle.dp
@ -131,6 +152,7 @@ ColumnLayout {
} }
} }
LabelButton { LabelButton {
visible: !mainItem.isConference
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: 56 * DefaultStyle.dp width: 56 * DefaultStyle.dp
height: 56 * DefaultStyle.dp height: 56 * DefaultStyle.dp
@ -141,7 +163,7 @@ ColumnLayout {
button.onClicked: console.debug("[CallPage.qml] TODO : open conversation") button.onClicked: console.debug("[CallPage.qml] TODO : open conversation")
} }
LabelButton { LabelButton {
id: videoCall visible: !mainItem.isConference
anchors.right: parent.right anchors.right: parent.right
width: 56 * DefaultStyle.dp width: 56 * DefaultStyle.dp
height: 56 * DefaultStyle.dp height: 56 * DefaultStyle.dp

View file

@ -49,10 +49,6 @@ AbstractMainPage {
listStackView.push(newCallItem) listStackView.push(newCallItem)
} }
function createCall(addr) {
UtilsCpp.createCall(addr)
}
Dialog { Dialog {
id: deleteHistoryPopup id: deleteHistoryPopup
width: 278 * DefaultStyle.dp width: 278 * DefaultStyle.dp
@ -316,9 +312,13 @@ AbstractMainPage {
icon.height: 24 * DefaultStyle.dp icon.height: 24 * DefaultStyle.dp
onClicked: { onClicked: {
if (modelData.core.isConference) { if (modelData.core.isConference) {
var callsWindow = UtilsCpp.getCallsWindow()
callsWindow.setupConference(modelData.core.conferenceInfo)
callsWindow.show()
}
else {
UtilsCpp.createCall(modelData.core.remoteAddress)
} }
else UtilsCpp.createCall(modelData.core.remoteAddress)
} }
} }
} }
@ -515,7 +515,8 @@ AbstractMainPage {
id: contactDetail id: contactDetail
visible: mainItem.selectedRowHistoryGui != undefined visible: mainItem.selectedRowHistoryGui != undefined
property var contactObj: UtilsCpp.findFriendByAddress(contactAddress) property var contactObj: UtilsCpp.findFriendByAddress(contactAddress)
contact: contactObj && contactObj.value || null contact: contactObj && contactObj.value || null
conferenceInfo: mainItem.selectedRowHistoryGui && mainItem.selectedRowHistoryGui.core.conferenceInfo
contactAddress: mainItem.selectedRowHistoryGui && mainItem.selectedRowHistoryGui.core.remoteAddress || "" contactAddress: mainItem.selectedRowHistoryGui && mainItem.selectedRowHistoryGui.core.remoteAddress || ""
contactName: mainItem.selectedRowHistoryGui ? mainItem.selectedRowHistoryGui.core.displayName : "" contactName: mainItem.selectedRowHistoryGui ? mainItem.selectedRowHistoryGui.core.displayName : ""
anchors.top: rightPanelStackView.top anchors.top: rightPanelStackView.top
@ -546,7 +547,11 @@ AbstractMainPage {
text: qsTr("Copier l'adresse SIP") text: qsTr("Copier l'adresse SIP")
iconSource: AppIcons.copy iconSource: AppIcons.copy
} }
onClicked: UtilsCpp.copyToClipboard(mainItem.selectedRowHistoryGui && mainItem.selectedRowHistoryGui.core.remoteAddress) onClicked: {
var success = UtilsCpp.copyToClipboard(mainItem.selectedRowHistoryGui && mainItem.selectedRowHistoryGui.core.remoteAddress)
if (success) UtilsCpp.showInformationPopup(qsTr("Copié"), qsTr("L'adresse a été copiée dans le presse-papier"), true)
else UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("Erreur lors de la copie de l'adresse"), false)
}
} }
Button { Button {
background: Item {} background: Item {}
@ -626,7 +631,7 @@ AbstractMainPage {
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere || modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted || modelData.core.status === LinphoneEnums.CallStatus.Aborted
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted || modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted
? AppIcons.arrowElbow ? AppIcons.arrowElbow
: modelData.core.isOutgoing : modelData.core.isOutgoing
? AppIcons.arrowUpRight ? AppIcons.arrowUpRight
: AppIcons.arrowDownLeft : AppIcons.arrowDownLeft

View file

@ -271,15 +271,13 @@ AbstractMainPage {
visible: mainItem.selectedContact != undefined visible: mainItem.selectedContact != undefined
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Control.StackView.onActivated: Control.StackView.onActivated: mainItem.leftPanelEnabled = true
mainItem.leftPanelEnabled = true
Control.StackView.onDeactivated: mainItem.leftPanelEnabled = false Control.StackView.onDeactivated: mainItem.leftPanelEnabled = false
ContactLayout { ContactLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.topMargin: 45 * DefaultStyle.dp Layout.topMargin: 45 * DefaultStyle.dp
Layout.leftMargin: 74 * DefaultStyle.dp
contact: mainItem.selectedContact contact: mainItem.selectedContact
Layout.preferredWidth: 360 * DefaultStyle.dp Layout.preferredWidth: 360 * DefaultStyle.dp
buttonContent: Button { buttonContent: Button {
@ -296,8 +294,9 @@ AbstractMainPage {
Layout.preferredWidth: 360 * DefaultStyle.dp Layout.preferredWidth: 360 * DefaultStyle.dp
spacing: 32 * DefaultStyle.dp spacing: 32 * DefaultStyle.dp
ColumnLayout { ColumnLayout {
spacing: 15 * DefaultStyle.dp spacing: 9 * DefaultStyle.dp
Text { Text {
Layout.leftMargin: 10 * DefaultStyle.dp
text: qsTr("Informations") text: qsTr("Informations")
font { font {
pixelSize: 16 * DefaultStyle.dp pixelSize: 16 * DefaultStyle.dp
@ -309,27 +308,32 @@ AbstractMainPage {
Layout.preferredHeight: Math.min(226 * DefaultStyle.dp, addrList.contentHeight + topPadding + bottomPadding) Layout.preferredHeight: Math.min(226 * DefaultStyle.dp, addrList.contentHeight + topPadding + bottomPadding)
height: Math.min(226 * DefaultStyle.dp, addrList.contentHeight) height: Math.min(226 * DefaultStyle.dp, addrList.contentHeight)
Layout.fillWidth: true Layout.fillWidth: true
topPadding: 12 * DefaultStyle.dp
bottomPadding: 12 * DefaultStyle.dp
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
contentItem: ListView { contentItem: ListView {
id: addrList id: addrList
width: 360 * DefaultStyle.dp width: 360 * DefaultStyle.dp
height: contentHeight height: contentHeight
clip: true clip: true
spacing: 9 * DefaultStyle.dp
model: VariantList { model: VariantList {
model: mainItem.selectedContact ? mainItem.selectedContact.core.allAddresses : [] model: mainItem.selectedContact ? mainItem.selectedContact.core.allAddresses : []
} }
delegate: Item { delegate: Item {
width: addrList.width width: addrList.width
height: 70 * DefaultStyle.dp height: 46 * DefaultStyle.dp
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 5 * DefaultStyle.dp // anchors.topMargin: 5 * DefaultStyle.dp
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
// Layout.fillHeight: true // Layout.fillHeight: true
// Layout.alignment: Qt.AlignVCenter // Layout.alignment: Qt.AlignVCenter
Layout.topMargin: 10 * DefaultStyle.dp // Layout.topMargin: 10 * DefaultStyle.dp
Layout.bottomMargin: 10 * DefaultStyle.dp // Layout.bottomMargin: 10 * DefaultStyle.dp
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
Text { Text {
@ -384,6 +388,10 @@ AbstractMainPage {
RoundedBackgroundControl { RoundedBackgroundControl {
visible: companyText.text.length != 0 || jobText.text.length != 0 visible: companyText.text.length != 0 || jobText.text.length != 0
Layout.fillWidth: true Layout.fillWidth: true
topPadding: 12 * DefaultStyle.dp
bottomPadding: 12 * DefaultStyle.dp
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
// Layout.fillHeight: true // Layout.fillHeight: true
contentItem: ColumnLayout { contentItem: ColumnLayout {
@ -462,11 +470,13 @@ AbstractMainPage {
} }
ColumnLayout { ColumnLayout {
spacing: 10 * DefaultStyle.dp spacing: 10 * DefaultStyle.dp
Layout.rightMargin: 90 * DefaultStyle.dp
ColumnLayout { ColumnLayout {
visible: false visible: false
RowLayout { RowLayout {
Text { Text {
text: qsTr("Confiance") text: qsTr("Confiance")
Layout.leftMargin: 10 * DefaultStyle.dp
font { font {
pixelSize: 16 * DefaultStyle.dp pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp weight: 800 * DefaultStyle.dp
@ -482,7 +492,10 @@ AbstractMainPage {
} }
} }
ColumnLayout { ColumnLayout {
spacing: 9 * DefaultStyle.dp
Text { Text {
Layout.preferredHeight: 22 * DefaultStyle.dp
Layout.leftMargin: 10 * DefaultStyle.dp
text: qsTr("Other actions") text: qsTr("Other actions")
font { font {
pixelSize: 16 * DefaultStyle.dp pixelSize: 16 * DefaultStyle.dp

View file

@ -19,6 +19,7 @@ AbstractMainPage {
signal returnRequested() signal returnRequested()
signal addParticipantsValidated(list<string> selectedParticipants) signal addParticipantsValidated(list<string> selectedParticipants)
Component.onCompleted: rightPanelStackView.push(overridenRightPanel, Control.StackView.Immediate) Component.onCompleted: rightPanelStackView.push(overridenRightPanel, Control.StackView.Immediate)
showDefaultItem: false//leftPanelStackView.currentItem.objectName === "listLayout"
onSelectedConferenceChanged: { onSelectedConferenceChanged: {
overridenRightPanelStackView.clear() overridenRightPanelStackView.clear()
@ -27,15 +28,7 @@ AbstractMainPage {
} }
} }
Connections { function editConference(confInfoGui = null) {
target: leftPanelStackView
onCurrentItemChanged: {
mainItem.showDefaultItem = leftPanelStackView.currentItem == listLayout && mainItem.meetingListCount === 0
}
}
onMeetingListCountChanged: showDefaultItem = leftPanelStackView.currentItem == listLayout && meetingListCount === 0
function setUpConference(confInfoGui = null) {
var isCreation = !confInfoGui var isCreation = !confInfoGui
if (isCreation) { if (isCreation) {
confInfoGui = Qt.createQmlObject('import Linphone confInfoGui = Qt.createQmlObject('import Linphone
@ -126,13 +119,24 @@ AbstractMainPage {
Component { Component {
id: listLayout id: listLayout
ColumnLayout { ColumnLayout {
id: listLayoutIn
spacing: 0 spacing: 0
property string objectName: "listLayout"
Control.StackView.onDeactivated: { Control.StackView.onDeactivated: {
mainItem.selectedConference = null mainItem.selectedConference = null
// mainItem.showDefaultItem.visible = false
// mainItem.righPanelStackView.clear() // mainItem.righPanelStackView.clear()
} }
Control.StackView.onActivated: { Control.StackView.onActivated: {
mainItem.selectedConference = conferenceList.selectedConference mainItem.selectedConference = conferenceList.selectedConference
// mainItem.showDefaultItem = conferenceList.count == 0
}
Binding {
target: mainItem
when: leftPanelStackView.currentItem.objectName === "listLayout"
property: "showDefaultItem"
value: conferenceList.count === 0
restoreMode: Binding.RestoreBindingOrValue
} }
RowLayout { RowLayout {
enabled: mainItem.leftPanelEnabled enabled: mainItem.leftPanelEnabled
@ -155,7 +159,7 @@ AbstractMainPage {
icon.width: 28 * DefaultStyle.dp icon.width: 28 * DefaultStyle.dp
icon.height: 28 * DefaultStyle.dp icon.height: 28 * DefaultStyle.dp
onClicked: { onClicked: {
mainItem.setUpConference() mainItem.editConference()
} }
} }
} }
@ -169,6 +173,7 @@ AbstractMainPage {
} }
Text { Text {
Layout.topMargin: 38 * DefaultStyle.dp
Layout.fillHeight: true Layout.fillHeight: true
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
text: mainItem.emptyListText text: mainItem.emptyListText
@ -193,12 +198,6 @@ AbstractMainPage {
onSelectedConferenceChanged: { onSelectedConferenceChanged: {
mainItem.selectedConference = selectedConference mainItem.selectedConference = selectedConference
} }
onCountChanged: {
mainItem.meetingListCount = count
}
Connections {
target: mainItem
}
Control.ScrollBar.vertical: ScrollBar { Control.ScrollBar.vertical: ScrollBar {
id: meetingsScrollbar id: meetingsScrollbar
anchors.right: parent.right anchors.right: parent.right
@ -494,7 +493,7 @@ AbstractMainPage {
icon.source: AppIcons.pencil icon.source: AppIcons.pencil
contentImageColor: DefaultStyle.main1_500_main contentImageColor: DefaultStyle.main1_500_main
background: Item{} background: Item{}
onClicked: mainItem.setUpConference(mainItem.selectedConference) onClicked: mainItem.editConference(mainItem.selectedConference)
} }
PopupButton { PopupButton {
id: deletePopup id: deletePopup
@ -718,7 +717,9 @@ AbstractMainPage {
bottomPadding: 11 * DefaultStyle.dp bottomPadding: 11 * DefaultStyle.dp
onClicked: { onClicked: {
console.log(mainItem.selectedConference.core.uri) console.log(mainItem.selectedConference.core.uri)
UtilsCpp.setupConference(mainItem.selectedConference) var callsWindow = UtilsCpp.getCallsWindow()
callsWindow.setupConference(mainItem.selectedConference)
callsWindow.show()
} }
} }
Item { Layout.fillHeight: true} Item { Layout.fillHeight: true}

View file

@ -5,6 +5,7 @@ QtObject {
property string welcomeLinphoneLogo: "image://internal/linphone.svg" property string welcomeLinphoneLogo: "image://internal/linphone.svg"
property string welcomeLock: "image://internal/secured.svg" property string welcomeLock: "image://internal/secured.svg"
property string lock: "image://internal/lock.svg" property string lock: "image://internal/lock.svg"
property string lockSimple: "image://internal/lock-simple.svg"
property string welcomeOpenSource: "image://internal/open_source.svg" property string welcomeOpenSource: "image://internal/open_source.svg"
property string eyeHide: "image://internal/eye.svg" property string eyeHide: "image://internal/eye.svg"
property string eyeShow: "image://internal/eye-slash.svg" property string eyeShow: "image://internal/eye-slash.svg"