group call (ui to fix) + create call ui from callCreated signal

This commit is contained in:
Gaelle Braud 2024-04-09 16:57:51 +02:00 committed by Julien Wadel
parent cba34e82c0
commit 06a80173e6
26 changed files with 246 additions and 91 deletions

View file

@ -90,6 +90,23 @@ App::App(int &argc, char *argv[])
App::~App() { App::~App() {
} }
void App::setSelf(QSharedPointer<App>(me)) {
mCoreModelConnection = QSharedPointer<SafeConnection<App, CoreModel>>(
new SafeConnection<App, CoreModel>(me, CoreModel::getInstance()), &QObject::deleteLater);
mCoreModelConnection->makeConnectToModel(&CoreModel::callCreated,
[this](const std::shared_ptr<linphone::Call> &call) {
auto callCore = CallCore::create(call);
mCoreModelConnection->invokeToCore([this, callCore] {
auto callGui = new CallGui(callCore);
auto win = getCallsWindow(QVariant::fromValue(callGui));
Utils::smartShowWindow(win);
qDebug() << "App : call created" << callGui;
// callGui.value<CallGui
// * > ()->getCore()->lSetCameraEnabled(true);
});
});
}
App *App::getInstance() { App *App::getInstance() {
return dynamic_cast<App *>(QApplication::instance()); return dynamic_cast<App *>(QApplication::instance());
} }
@ -148,7 +165,7 @@ void App::init() {
Qt::QueuedConnection); Qt::QueuedConnection);
mEngine->load(url); mEngine->load(url);
}); });
coreModel.reset(); // coreModel.reset();
}, },
Qt::SingleShotConnection); Qt::SingleShotConnection);
// Console Commands // Console Commands

View file

@ -36,6 +36,7 @@ class App : public SingleApplication, public AbstractObject {
public: public:
App(int &argc, char *argv[]); App(int &argc, char *argv[]);
~App(); ~App();
void setSelf(QSharedPointer<App>(me));
static App *getInstance(); static App *getInstance();
Notifier *getNotifier() const; Notifier *getNotifier() const;
@ -121,6 +122,7 @@ private:
QQuickWindow *mMainWindow = nullptr; QQuickWindow *mMainWindow = nullptr;
QQuickWindow *mCallsWindow = nullptr; QQuickWindow *mCallsWindow = nullptr;
QSharedPointer<Settings> mSettings; QSharedPointer<Settings> mSettings;
QSharedPointer<SafeConnection<App, CoreModel>> mCoreModelConnection;
DECLARE_ABSTRACT_OBJECT DECLARE_ABSTRACT_OBJECT
}; };

View file

@ -44,6 +44,14 @@ ConferenceInfoCore::ConferenceInfoCore(std::shared_ptr<linphone::ConferenceInfo>
mTimeZoneModel = QSharedPointer<TimeZoneModel>(new TimeZoneModel( mTimeZoneModel = QSharedPointer<TimeZoneModel>(new TimeZoneModel(
QTimeZone::systemTimeZone())); // Always return system timezone because this info is not stored in database. QTimeZone::systemTimeZone())); // Always return system timezone because this info is not stored in database.
connect(this, &ConferenceInfoCore::dateTimeChanged, [this] {
setDuration(mDateTime.secsTo(mEndDateTime) / 60.0);
setIsScheduled(mDateTime != QDateTime::currentDateTime());
});
connect(this, &ConferenceInfoCore::endDateTimeChanged,
[this] { setDuration(mDateTime.secsTo(mEndDateTime) / 60.0); });
connect(this, &ConferenceInfoCore::durationChanged, [this] { setEndDateTime(mDateTime.addSecs(mDuration * 60)); });
if (conferenceInfo) { if (conferenceInfo) {
mustBeInLinphoneThread(getClassName()); mustBeInLinphoneThread(getClassName());
mConferenceInfoModel = Utils::makeQObject_ptr<ConferenceInfoModel>(conferenceInfo); mConferenceInfoModel = Utils::makeQObject_ptr<ConferenceInfoModel>(conferenceInfo);
@ -85,8 +93,8 @@ ConferenceInfoCore::ConferenceInfoCore(std::shared_ptr<linphone::ConferenceInfo>
} }
mConferenceInfoState = LinphoneEnums::fromLinphone(conferenceInfo->getState()); mConferenceInfoState = LinphoneEnums::fromLinphone(conferenceInfo->getState());
} else { } else {
mDateTime = QDateTime::currentDateTime(); mDateTime = QDateTime();
mEndDateTime = QDateTime::currentDateTime().addSecs(3600); mEndDateTime = mDateTime;
App::postModelSync([this]() { App::postModelSync([this]() {
auto defaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount(); auto defaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
if (defaultAccount) { if (defaultAccount) {
@ -100,11 +108,6 @@ ConferenceInfoCore::ConferenceInfoCore(std::shared_ptr<linphone::ConferenceInfo>
} }
}); });
} }
connect(this, &ConferenceInfoCore::dateTimeChanged, [this] { setDuration(mDateTime.secsTo(mEndDateTime) / 60.0); });
connect(this, &ConferenceInfoCore::endDateTimeChanged,
[this] { setDuration(mDateTime.secsTo(mEndDateTime) / 60.0); });
connect(this, &ConferenceInfoCore::durationChanged, [this] { setEndDateTime(mDateTime.addSecs(mDuration * 60)); });
} }
ConferenceInfoCore::ConferenceInfoCore(const ConferenceInfoCore &conferenceInfoCore) { ConferenceInfoCore::ConferenceInfoCore(const ConferenceInfoCore &conferenceInfoCore) {
@ -185,10 +188,18 @@ void ConferenceInfoCore::setSelf(QSharedPointer<ConferenceInfoCore> me) {
mConfInfoModelConnection->makeConnectToModel( mConfInfoModelConnection->makeConnectToModel(
&ConferenceInfoModel::schedulerStateChanged, [this](linphone::ConferenceScheduler::State state) { &ConferenceInfoModel::schedulerStateChanged, [this](linphone::ConferenceScheduler::State state) {
auto confInfoState = mConferenceInfoModel->getState(); auto confInfoState = mConferenceInfoModel->getState();
QString uri;
if (state == linphone::ConferenceScheduler::State::Ready)
uri = mConferenceInfoModel->getConferenceScheduler()->getUri();
mConfInfoModelConnection->invokeToCore([this, state = LinphoneEnums::fromLinphone(state), mConfInfoModelConnection->invokeToCore([this, state = LinphoneEnums::fromLinphone(state),
infoState = LinphoneEnums::fromLinphone(confInfoState)] { infoState = LinphoneEnums::fromLinphone(confInfoState),
uri] {
qDebug() << "scheduler state changed" << state;
setConferenceSchedulerState(state); setConferenceSchedulerState(state);
setConferenceInfoState(infoState); setConferenceInfoState(infoState);
if (state == LinphoneEnums::ConferenceSchedulerState::Ready) {
setUri(uri);
}
}); });
}); });
mConfInfoModelConnection->makeConnectToModel( mConfInfoModelConnection->makeConnectToModel(
@ -199,6 +210,12 @@ void ConferenceInfoCore::setSelf(QSharedPointer<ConferenceInfoCore> me) {
} else { // Create } else { // Create
mCoreModelConnection = QSharedPointer<SafeConnection<ConferenceInfoCore, CoreModel>>( mCoreModelConnection = QSharedPointer<SafeConnection<ConferenceInfoCore, CoreModel>>(
new SafeConnection<ConferenceInfoCore, CoreModel>(me, CoreModel::getInstance()), &QObject::deleteLater); new SafeConnection<ConferenceInfoCore, CoreModel>(me, CoreModel::getInstance()), &QObject::deleteLater);
mCoreModelConnection->makeConnectToModel(
&CoreModel::conferenceInfoReceived,
[this](const std::shared_ptr<linphone::Core> &core,
const std::shared_ptr<const linphone::ConferenceInfo> &conferenceInfo) {
qDebug() << "CONF INFO RECEIVED ==================";
});
} }
} }
} }
@ -359,6 +376,25 @@ void ConferenceInfoCore::addParticipant(const QString &address) {
emit participantsChanged(); emit participantsChanged();
} }
void ConferenceInfoCore::addParticipants(const QStringList &addresses) {
bool addressAdded = false;
for (auto &address : addresses) {
auto found = std::find_if(mParticipants.begin(), mParticipants.end(), [address](QVariant participant) {
return participant.toMap()["address"].toString() == address;
});
if (found == mParticipants.end()) {
QVariantMap participant;
auto displayNameObj = Utils::getDisplayName(address);
participant["displayName"] = displayNameObj ? displayNameObj->getValue() : "";
participant["address"] = address;
participant["role"] = (int)LinphoneEnums::ParticipantRole::Listener;
mParticipants.append(participant);
addressAdded = true;
}
}
if (addressAdded) emit participantsChanged();
}
void ConferenceInfoCore::removeParticipant(const QString &address) { void ConferenceInfoCore::removeParticipant(const QString &address) {
for (int i = 0; i < mParticipants.size(); ++i) { for (int i = 0; i < mParticipants.size(); ++i) {
auto map = mParticipants[i].toMap(); auto map = mParticipants[i].toMap();
@ -435,6 +471,9 @@ LinphoneEnums::ConferenceSchedulerState ConferenceInfoCore::getConferenceSchedul
// Datetime is in Custom (Locale/UTC/System). Convert into UTC for conference info // Datetime is in Custom (Locale/UTC/System). Convert into UTC for conference info
void ConferenceInfoCore::setIsScheduled(const bool &on) { void ConferenceInfoCore::setIsScheduled(const bool &on) {
if (!on) setDateTime(QDateTime());
else mDateTime = QDateTime::currentDateTime();
qDebug() << "set d ate time valid" << mDateTime.isValid();
if (mIsScheduled != on) { if (mIsScheduled != on) {
mIsScheduled = on; mIsScheduled = on;
emit isScheduledChanged(); emit isScheduledChanged();

View file

@ -112,6 +112,7 @@ public:
void setConferenceSchedulerState(LinphoneEnums::ConferenceSchedulerState state); void setConferenceSchedulerState(LinphoneEnums::ConferenceSchedulerState state);
Q_INVOKABLE void addParticipant(const QString &address); Q_INVOKABLE void addParticipant(const QString &address);
Q_INVOKABLE void addParticipants(const QStringList &addresses);
Q_INVOKABLE void removeParticipant(const QString &address); Q_INVOKABLE void removeParticipant(const QString &address);
Q_INVOKABLE void removeParticipant(const int &index); Q_INVOKABLE void removeParticipant(const int &index);
Q_INVOKABLE QString getParticipantAddressAt(const int &index); Q_INVOKABLE QString getParticipantAddressAt(const int &index);

View file

@ -94,6 +94,10 @@ void ConferenceInfoList::setSelf(QSharedPointer<ConferenceInfoList> me) {
qDebug() << "list: conf state changed"; qDebug() << "list: conf state changed";
lUpdate(); lUpdate();
}); });
mCoreModelConnection->makeConnectToModel(
&CoreModel::callCreated, [this](const std::shared_ptr<linphone::Call> &call) {
qDebug() << "call created" << Utils::coreStringToAppString(call->getRemoteAddress()->asString());
});
mCoreModelConnection->makeConnectToModel( mCoreModelConnection->makeConnectToModel(
&CoreModel::conferenceInfoReceived, &CoreModel::conferenceInfoReceived,
[this](const std::shared_ptr<linphone::Core> &core, [this](const std::shared_ptr<linphone::Core> &core,

View file

@ -28,14 +28,15 @@ int main(int argc, char *argv[]) {
// Disable QML cache. Avoid malformed cache. // Disable QML cache. Avoid malformed cache.
qputenv("QML_DISABLE_DISK_CACHE", "true"); qputenv("QML_DISABLE_DISK_CACHE", "true");
App app(argc, argv); auto app = QSharedPointer<App>::create(argc, argv);
app->setSelf(app);
QTranslator translator; QTranslator translator;
const QStringList uiLanguages = QLocale::system().uiLanguages(); const QStringList uiLanguages = QLocale::system().uiLanguages();
for (const QString &locale : uiLanguages) { for (const QString &locale : uiLanguages) {
const QString baseName = "Linphone_" + QLocale(locale).name(); const QString baseName = "Linphone_" + QLocale(locale).name();
if (translator.load(":/i18n/" + baseName)) { if (translator.load(":/i18n/" + baseName)) {
app.installTranslator(&translator); app->installTranslator(&translator);
break; break;
} }
} }
@ -47,9 +48,11 @@ int main(int argc, char *argv[]) {
int result = 0; int result = 0;
do { do {
result = app.exec(); result = app->exec();
} while (result == (int)App::StatusCode::gRestartCode); } while (result == (int)App::StatusCode::gRestartCode);
qWarning() << "[Main] Exiting app with the code : " << result; qWarning() << "[Main] Exiting app with the code : " << result;
app.clean(); app->clean();
app = nullptr;
return result; return result;
} }

View file

@ -100,12 +100,18 @@ QString ConferenceInfoModel::getDescription() const {
return Utils::coreStringToAppString(mConferenceInfo->getSubject()); return Utils::coreStringToAppString(mConferenceInfo->getSubject());
} }
QString ConferenceInfoModel::getUri() const {
if (auto uriAddr = mConferenceInfo->getUri()) {
return Utils::coreStringToAppString(uriAddr->asString());
} else return QString();
}
std::list<std::shared_ptr<linphone::ParticipantInfo>> ConferenceInfoModel::getParticipantInfos() const { std::list<std::shared_ptr<linphone::ParticipantInfo>> ConferenceInfoModel::getParticipantInfos() const {
return mConferenceInfo->getParticipantInfos(); return mConferenceInfo->getParticipantInfos();
} }
void ConferenceInfoModel::setDateTime(const QDateTime &date) { void ConferenceInfoModel::setDateTime(const QDateTime &date) {
mConferenceInfo->setDateTime(date.toMSecsSinceEpoch() / 1000); // toMSecsSinceEpoch() is UTC mConferenceInfo->setDateTime(date.isValid() ? date.toMSecsSinceEpoch() / 1000 : -1); // toMSecsSinceEpoch() is UTC
emit dateTimeChanged(date); emit dateTimeChanged(date);
} }

View file

@ -46,6 +46,7 @@ public:
QString getOrganizerName() const; QString getOrganizerName() const;
QString getOrganizerAddress() const; QString getOrganizerAddress() const;
QString getDescription() const; QString getDescription() const;
QString getUri() const;
std::list<std::shared_ptr<linphone::ParticipantInfo>> getParticipantInfos() const; std::list<std::shared_ptr<linphone::ParticipantInfo>> getParticipantInfos() const;
void setDateTime(const QDateTime &date); void setDateTime(const QDateTime &date);

View file

@ -23,6 +23,7 @@
#include <QDebug> #include <QDebug>
#include "model/core/CoreModel.hpp" #include "model/core/CoreModel.hpp"
#include "tool/Utils.hpp"
DEFINE_ABSTRACT_OBJECT(ConferenceSchedulerModel) DEFINE_ABSTRACT_OBJECT(ConferenceSchedulerModel)
@ -39,6 +40,13 @@ ConferenceSchedulerModel::~ConferenceSchedulerModel() {
mustBeInLinphoneThread("~" + getClassName()); mustBeInLinphoneThread("~" + getClassName());
} }
QString ConferenceSchedulerModel::getUri() {
auto uriAddr = mMonitor->getInfo() ? mMonitor->getInfo()->getUri() : nullptr;
if (uriAddr) {
return Utils::coreStringToAppString(uriAddr->asString());
} else return QString();
}
void ConferenceSchedulerModel::setInfo(const std::shared_ptr<linphone::ConferenceInfo> &confInfo) { void ConferenceSchedulerModel::setInfo(const std::shared_ptr<linphone::ConferenceInfo> &confInfo) {
mMonitor->setInfo(confInfo); mMonitor->setInfo(confInfo);
} }

View file

@ -38,6 +38,7 @@ public:
QObject *parent = nullptr); QObject *parent = nullptr);
~ConferenceSchedulerModel(); ~ConferenceSchedulerModel();
QString getUri();
void setInfo(const std::shared_ptr<linphone::ConferenceInfo> &confInfo); void setInfo(const std::shared_ptr<linphone::ConferenceInfo> &confInfo);
void cancelConference(const std::shared_ptr<linphone::ConferenceInfo> &confInfo); void cancelConference(const std::shared_ptr<linphone::ConferenceInfo> &confInfo);

View file

@ -93,11 +93,12 @@ QString ToolModel::getDisplayName(QString address) {
return displayName.isEmpty() ? address : displayName; return displayName.isEmpty() ? address : displayName;
} }
QSharedPointer<CallCore> ToolModel::createCall(const QString &sipAddress, bool ToolModel::createCall(const QString &sipAddress,
const QVariantMap &options, const QVariantMap &options,
const QString &prepareTransfertAddress, const QString &prepareTransfertAddress,
const QHash<QString, QString> &headers, const QHash<QString, QString> &headers,
linphone::MediaEncryption mediaEncryption) { linphone::MediaEncryption mediaEncryption,
QString *errorMessage) {
bool waitRegistrationForCall = true; // getSettingsModel()->getWaitRegistrationForCall() bool waitRegistrationForCall = true; // getSettingsModel()->getWaitRegistrationForCall()
std::shared_ptr<linphone::Core> core = CoreModel::getInstance()->getCore(); std::shared_ptr<linphone::Core> core = CoreModel::getInstance()->getCore();
bool cameraEnabled = options.contains("cameraEnabled") ? options["cameraEnabled"].toBool() : false; bool cameraEnabled = options.contains("cameraEnabled") ? options["cameraEnabled"].toBool() : false;
@ -106,7 +107,11 @@ QSharedPointer<CallCore> ToolModel::createCall(const QString &sipAddress,
if (!address) { if (!address) {
qCritical() << "[" + QString(gClassName) + "] The calling address is not an interpretable SIP address: " qCritical() << "[" + QString(gClassName) + "] The calling address is not an interpretable SIP address: "
<< sipAddress; << sipAddress;
return nullptr; if (errorMessage) {
*errorMessage = tr("The calling address is not an interpretable SIP address : ");
errorMessage->append(sipAddress);
}
return false;
} }
std::shared_ptr<linphone::CallParams> params = core->createCallParams(nullptr); std::shared_ptr<linphone::CallParams> params = core->createCallParams(nullptr);
@ -133,7 +138,7 @@ QSharedPointer<CallCore> ToolModel::createCall(const QString &sipAddress,
if (core->getDefaultAccount()) params->setAccount(core->getDefaultAccount()); if (core->getDefaultAccount()) params->setAccount(core->getDefaultAccount());
auto call = core->inviteAddressWithParams(address, params); auto call = core->inviteAddressWithParams(address, params);
call->enableCamera(cameraEnabled); call->enableCamera(cameraEnabled);
return call ? CallCore::create(call) : nullptr; return call != nullptr;
/* TODO transfer /* TODO transfer

View file

@ -46,11 +46,12 @@ public:
static QString getDisplayName(const std::shared_ptr<const linphone::Address> &address); static QString getDisplayName(const std::shared_ptr<const linphone::Address> &address);
static QString getDisplayName(QString address); static QString getDisplayName(QString address);
static QSharedPointer<CallCore> createCall(const QString &sipAddress, static bool createCall(const QString &sipAddress,
const QVariantMap &options = {}, const QVariantMap &options = {},
const QString &prepareTransfertAddress = "", const QString &prepareTransfertAddress = "",
const QHash<QString, QString> &headers = {}, const QHash<QString, QString> &headers = {},
linphone::MediaEncryption = linphone::MediaEncryption::None); linphone::MediaEncryption = linphone::MediaEncryption::None,
QString *errorMessage = nullptr);
private: private:
DECLARE_ABSTRACT_OBJECT DECLARE_ABSTRACT_OBJECT

View file

@ -94,32 +94,19 @@ QString Utils::getInitials(const QString &username) {
return QLocale().toUpper(initials.join("")); return QLocale().toUpper(initials.join(""));
} }
VariantObject *Utils::createCall(QString sipAddress, void Utils::createCall(const QString &sipAddress,
QVariantMap options, QVariantMap options,
QString prepareTransfertAddress, const QString &prepareTransfertAddress,
QHash<QString, QString> headers) { const QHash<QString, QString> &headers) {
VariantObject *data = new VariantObject(QVariant()); // Scope : GUI App::postModelAsync([sipAddress, options, prepareTransfertAddress, headers]() {
if (!data) return nullptr; QString errorMessage;
data->makeRequest([sipAddress, options, prepareTransfertAddress, headers]() { bool success = ToolModel::createCall(sipAddress, options, prepareTransfertAddress, headers,
auto call = ToolModel::createCall(sipAddress, options, prepareTransfertAddress, headers); linphone::MediaEncryption::None, &errorMessage);
if (call) { if (!success) {
auto callGui = QVariant::fromValue(new CallGui(call)); if (errorMessage.isEmpty()) errorMessage = tr("L'appel n'a pas pu être créé");
App::postCoreSync([callGui]() { showInformationPopup("Erreur", errorMessage, false);
auto app = App::getInstance();
auto window = app->getCallsWindow(callGui);
smartShowWindow(window);
qDebug() << "Utils : call created" << callGui;
// callGui.value<CallGui *>()->getCore()->lSetCameraEnabled(true);
});
return callGui;
} else {
qDebug() << "Utils : failed to create call";
return QVariant();
} }
}); });
data->requestValue();
return data;
} }
void Utils::setupConference(ConferenceInfoGui *confGui) { void Utils::setupConference(ConferenceInfoGui *confGui) {

View file

@ -58,10 +58,10 @@ public:
Q_INVOKABLE static QString getFamilyNameFromFullName(const QString &fullName); Q_INVOKABLE static QString getFamilyNameFromFullName(const QString &fullName);
Q_INVOKABLE static QString getInitials(const QString &username); // Support UTF32 Q_INVOKABLE static QString getInitials(const QString &username); // Support UTF32
Q_INVOKABLE static VariantObject *createCall(QString sipAddress, Q_INVOKABLE static void createCall(const QString &sipAddress,
QVariantMap options = {}, QVariantMap options = {},
QString prepareTransfertAddress = "", const QString &prepareTransfertAddress = "",
QHash<QString, QString> headers = {}); const QHash<QString, QString> &headers = {});
Q_INVOKABLE static void openCallsWindow(CallGui *call); Q_INVOKABLE static void openCallsWindow(CallGui *call);
Q_INVOKABLE static void setupConference(ConferenceInfoGui *confGui); Q_INVOKABLE static void setupConference(ConferenceInfoGui *confGui);
Q_INVOKABLE static void setCallsWindowCall(CallGui *call); Q_INVOKABLE static void setCallsWindowCall(CallGui *call);

View file

@ -32,12 +32,11 @@ Window {
&& (!conferenceInfo || conference) ) && (!conferenceInfo || conference) )
middleItemStackView.replace(inCallItem) middleItemStackView.replace(inCallItem)
} }
property var callObj
function joinConference(options) { 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) 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 { else {
callObj = UtilsCpp.createCall(conferenceInfo.core.uri, options) UtilsCpp.createCall(conferenceInfo.core.uri, options)
} }
} }
@ -462,14 +461,13 @@ Window {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: numPad.height Layout.preferredHeight: numPad.height
Layout.topMargin: 10 * DefaultStyle.dp Layout.topMargin: 10 * DefaultStyle.dp
property var callObj
NumericPad { NumericPad {
id: numPad id: numPad
width: parent.width width: parent.width
visible: parent.visible visible: parent.visible
closeButtonVisible: false closeButtonVisible: false
onLaunchCall: { onLaunchCall: {
callObj = UtilsCpp.createCall(dialerTextInput.text + "@sip.linphone.org") UtilsCpp.createCall(dialerTextInput.text + "@sip.linphone.org")
} }
} }
} }
@ -754,6 +752,10 @@ Window {
} }
participantsStack.selectedParticipants = selectedParticipants participantsStack.selectedParticipants = selectedParticipants
} }
onValidateRequested: {
conferenceInfoGui.core.resetParticipants(contactList.selectedContacts)
returnRequested()
}
Connections { Connections {
target: participantsStack target: participantsStack
onCurrentItemChanged: { onCurrentItemChanged: {

View file

@ -232,7 +232,7 @@ Item {
source: AppIcons.phone source: AppIcons.phone
} }
onClicked: { onClicked: {
mainItem.callObj = UtilsCpp.createCall(sipAddr.text) UtilsCpp.createCall(sipAddr.text)
} }
} }
Button { Button {
@ -245,7 +245,7 @@ Item {
height: 24 * DefaultStyle.dp height: 24 * DefaultStyle.dp
source: AppIcons.videoCamera source: AppIcons.videoCamera
} }
onClicked: mainItem.callObj = UtilsCpp.createCall(sipAddr.text, {'cameraEnabled':true}) onClicked: UtilsCpp.createCall(sipAddr.text, {'cameraEnabled':true})
} }
} }
Button { Button {

View file

@ -14,6 +14,7 @@ Item {
property color searchBarColor: DefaultStyle.grey_100 property color searchBarColor: DefaultStyle.grey_100
property color searchBarBorderColor: "transparent" property color searchBarBorderColor: "transparent"
signal callButtonPressed(string address) signal callButtonPressed(string address)
signal groupCallCreationRequested()
clip: true clip: true
Popup { Popup {
@ -198,6 +199,7 @@ Item {
Layout.preferredHeight: 24 * DefaultStyle.dp Layout.preferredHeight: 24 * DefaultStyle.dp
} }
} }
onClicked: mainItem.groupCallCreationRequested()
} }
// RowLayout { // RowLayout {
@ -333,9 +335,8 @@ Item {
NumericPad { NumericPad {
id: numPad id: numPad
width: parent.width width: parent.width
property var callObj
onLaunchCall: { onLaunchCall: {
callObj = UtilsCpp.createCall(searchBar.text + "@sip.linphone.org") UtilsCpp.createCall(searchBar.text + "@sip.linphone.org")
// TODO : auto completion instead of sip linphone // TODO : auto completion instead of sip linphone
} }
} }

View file

@ -144,7 +144,6 @@ ListView {
anchors.rightMargin: 10 * DefaultStyle.dp anchors.rightMargin: 10 * DefaultStyle.dp
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
RowLayout{ RowLayout{
property var callObj
visible: mainItem.actionLayoutVisible visible: mainItem.actionLayoutVisible
spacing: 10 * DefaultStyle.dp spacing: 10 * DefaultStyle.dp
Button { Button {
@ -157,7 +156,7 @@ ListView {
height: 24 * DefaultStyle.dp height: 24 * DefaultStyle.dp
source: AppIcons.phone source: AppIcons.phone
} }
onClicked: callObj = UtilsCpp.createCall(modelData.core.defaultAddress) onClicked: UtilsCpp.createCall(modelData.core.defaultAddress)
} }
Button { Button {
Layout.preferredWidth: 24 * DefaultStyle.dp Layout.preferredWidth: 24 * DefaultStyle.dp
@ -169,7 +168,7 @@ ListView {
height: 24 * DefaultStyle.dp height: 24 * DefaultStyle.dp
source: AppIcons.videoCamera source: AppIcons.videoCamera
} }
onClicked: callObj = UtilsCpp.createCall(modelData.core.defaultAddress, {'cameraEnabled':true}) onClicked: UtilsCpp.createCall(modelData.core.defaultAddress, {'cameraEnabled':true})
} }
} }
PopupButton { PopupButton {

View file

@ -102,14 +102,14 @@ ListView {
radius: height/2 radius: height/2
property var isCurrentDay: UtilsCpp.isCurrentDay(dateTime) property var isCurrentDay: UtilsCpp.isCurrentDay(dateTime)
color: !isCurrentDay ? DefaultStyle.main1_500_main : "transparent" color: isCurrentDay ? DefaultStyle.main1_500_main : "transparent"
Component.onCompleted: if(isCurrentDay) mainItem.currentIndex = index Component.onCompleted: if(isCurrentDay) mainItem.currentIndex = index
Text { Text {
id: dayNumText id: dayNumText
anchors.centerIn: parent anchors.centerIn: parent
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
text: UtilsCpp.toDateDayString(dateTime) text: UtilsCpp.toDateDayString(dateTime)
color: !dayNum.isCurrentDay ? DefaultStyle.grey_0 : DefaultStyle.main2_500main color: dayNum.isCurrentDay ? DefaultStyle.grey_0 : DefaultStyle.main2_500main
wrapMode: Text.NoWrap wrapMode: Text.NoWrap
font { font {
pixelSize: 20 * DefaultStyle.dp pixelSize: 20 * DefaultStyle.dp

View file

@ -126,10 +126,9 @@ ColumnLayout {
button.icon.height: 24 * DefaultStyle.dp button.icon.height: 24 * DefaultStyle.dp
button.icon.source: AppIcons.phone button.icon.source: AppIcons.phone
label: qsTr("Appel") label: qsTr("Appel")
property var callObj
button.onClicked: { button.onClicked: {
var addr = UtilsCpp.generateLinphoneSipAddress(mainItem.contactAddress) var addr = UtilsCpp.generateLinphoneSipAddress(mainItem.contactAddress)
callObj = UtilsCpp.createCall(addr) UtilsCpp.createCall(addr)
} }
} }
LabelButton { LabelButton {
@ -151,10 +150,9 @@ ColumnLayout {
button.icon.height: 24 * DefaultStyle.dp button.icon.height: 24 * DefaultStyle.dp
button.icon.source: AppIcons.videoCamera button.icon.source: AppIcons.videoCamera
label: qsTr("Appel Video") label: qsTr("Appel Video")
property var callObj
button.onClicked: { button.onClicked: {
var addr = UtilsCpp.generateLinphoneSipAddress(mainItem.contactAddress) var addr = UtilsCpp.generateLinphoneSipAddress(mainItem.contactAddress)
callObj = UtilsCpp.createCall(addr) UtilsCpp.createCall(addr)
console.log("[CallPage.qml] TODO : enable video") console.log("[CallPage.qml] TODO : enable video")
} }
} }

View file

@ -7,6 +7,7 @@ import UtilsCpp 1.0
ColumnLayout { ColumnLayout {
id: mainItem id: mainItem
spacing: 10 * DefaultStyle.dp
property string title property string title
property string validateButtonText property string validateButtonText
property string placeHolderText: qsTr("Rechercher des contacts") property string placeHolderText: qsTr("Rechercher des contacts")
@ -15,7 +16,10 @@ ColumnLayout {
property int selectedParticipantsCount: selectedParticipants.length property int selectedParticipantsCount: selectedParticipants.length
property alias titleLayout: titleLayout property alias titleLayout: titleLayout
property ConferenceInfoGui conferenceInfoGui property ConferenceInfoGui conferenceInfoGui
property bool nameGroupCall: false
readonly property string groupName: groupCallName.text
signal returnRequested() signal returnRequested()
signal validateRequested()
// Layout.preferredWidth: 362 * DefaultStyle.dp // Layout.preferredWidth: 362 * DefaultStyle.dp
function clearSelectedParticipants() { function clearSelectedParticipants() {
@ -35,15 +39,28 @@ ColumnLayout {
icon.height: 24 * DefaultStyle.dp icon.height: 24 * DefaultStyle.dp
onClicked: mainItem.returnRequested() onClicked: mainItem.returnRequested()
} }
Text { ColumnLayout {
text: mainItem.title spacing: 0
color: mainItem.titleColor Text {
maximumLineCount: 1 text: mainItem.title
font { color: mainItem.titleColor
pixelSize: 18 * DefaultStyle.dp maximumLineCount: 1
weight: 800 * DefaultStyle.dp font {
pixelSize: 18 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
Layout.fillWidth: true
}
Text {
text: qsTr("%1 participant%2 sélectionné").arg(mainItem.selectedParticipantsCount).arg(mainItem.selectedParticipantsCount > 1 ? "s" : "")
color: DefaultStyle.main2_500main
maximumLineCount: 1
font {
pixelSize: 12 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
Layout.fillWidth: true
} }
Layout.fillWidth: true
} }
Button { Button {
Layout.preferredWidth: 70 * DefaultStyle.dp Layout.preferredWidth: 70 * DefaultStyle.dp
@ -55,11 +72,32 @@ ColumnLayout {
text: mainItem.validateButtonText text: mainItem.validateButtonText
textSize: 13 * DefaultStyle.dp textSize: 13 * DefaultStyle.dp
onClicked: { onClicked: {
mainItem.conferenceInfoGui.core.resetParticipants(contactList.selectedContacts) mainItem.validateRequested()
mainItem.returnRequested()
} }
} }
} }
ColumnLayout {
visible: mainItem.nameGroupCall
spacing: 0
RowLayout {
Text {
font.pixelSize: 13 * DefaultStyle.dp
font.weight: 700 * DefaultStyle.dp
text: qsTr("Nom du groupe")
}
Item{Layout.fillWidth: true}
Text {
font.pixelSize: 12 * DefaultStyle.dp
font.weight: 300 * DefaultStyle.dp
text: qsTr("Requis")
}
}
TextField {
id: groupCallName
Layout.fillWidth: true
Layout.preferredHeight: 49 * DefaultStyle.dp
}
}
ListView { ListView {
id: participantList id: participantList
Layout.fillWidth: true Layout.fillWidth: true

View file

@ -12,9 +12,20 @@ AbstractMainPage {
newItemIconSource: AppIcons.newCall newItemIconSource: AppIcons.newCall
property var selectedRowHistoryGui property var selectedRowHistoryGui
signal listViewUpdated() signal listViewUpdated()
property ConferenceInfoGui confInfoGui
Connections {
enabled: confInfoGui
target: confInfoGui ? confInfoGui.core : null
onConferenceSchedulerStateChanged: {
if (confInfoGui.core.schedulerState === LinphoneEnums.ConferenceSchedulerState.Ready) {
listStackView.pop()
}
}
}
onSelectedRowHistoryGuiChanged: { onSelectedRowHistoryGuiChanged: {
if (selectedRowHistoryGui) rightPanelStackView.replace(contactDetailComp, Control.StackView.Immediate) if (selectedRowHistoryGui) rightPanelStackView.replace(contactDetailComp, Control.StackView.Immediate)
else rightPanelStackView.replace(emptySelection, Control.StackView.Immediate) else rightPanelStackView.replace(emptySelection, Control.StackView.Immediate)
@ -53,6 +64,7 @@ AbstractMainPage {
property int leftMargin: 45 * DefaultStyle.dp property int leftMargin: 45 * DefaultStyle.dp
property int rightMargin: 39 * DefaultStyle.dp property int rightMargin: 39 * DefaultStyle.dp
} }
Component { Component {
id: historyListItem id: historyListItem
@ -260,7 +272,6 @@ AbstractMainPage {
Button { Button {
Layout.rightMargin: 5 * DefaultStyle.dp Layout.rightMargin: 5 * DefaultStyle.dp
padding: 0 padding: 0
property var callObj
background: Item { background: Item {
visible: false visible: false
} }
@ -271,7 +282,7 @@ AbstractMainPage {
icon.height: 24 * DefaultStyle.dp icon.height: 24 * DefaultStyle.dp
onClicked: { onClicked: {
var addr = UtilsCpp.generateLinphoneSipAddress(modelData.core.remoteAddress) var addr = UtilsCpp.generateLinphoneSipAddress(modelData.core.remoteAddress)
callObj = UtilsCpp.createCall(addr) UtilsCpp.createCall(addr)
} }
} }
} }
@ -319,6 +330,7 @@ AbstractMainPage {
active: true active: true
policy: Control.ScrollBar.AlwaysOn //Control.ScrollBar.AsNeeded policy: Control.ScrollBar.AlwaysOn //Control.ScrollBar.AsNeeded
Layout.fillHeight: true Layout.fillHeight: true
Layout.rightMargin: 8 * DefaultStyle.dp
Rectangle{// TODO: change colors of scrollbar! Rectangle{// TODO: change colors of scrollbar!
anchors.fill: parent anchors.fill: parent
color: 'red' color: 'red'
@ -364,15 +376,44 @@ AbstractMainPage {
Layout.fillHeight: true Layout.fillHeight: true
groupCallVisible: true groupCallVisible: true
searchBarColor: DefaultStyle.grey_100 searchBarColor: DefaultStyle.grey_100
property var callObj
onCallButtonPressed: (address) => { onCallButtonPressed: (address) => {
callObj = UtilsCpp.createCall(UtilsCpp.generateLinphoneSipAddress(address)) UtilsCpp.createCall(UtilsCpp.generateLinphoneSipAddress(address))
// var window = UtilsCpp.getCallsWindow() // var window = UtilsCpp.getCallsWindow()
} }
onGroupCallCreationRequested: {
console.log("groupe call requetsed")
listStackView.push(groupCallItem)
}
} }
} }
} }
Component {
id: groupCallItem
// RowLayout {
AddParticipantsLayout {
Control.StackView.onActivated: mainItem.confInfoGui = Qt.createQmlObject('import Linphone
ConferenceInfoGui{
}', mainItem)
Layout.leftMargin: 21 * DefaultStyle.dp
title: qsTr("Appel de groupe")
titleColor: DefaultStyle.main1_500_main
nameGroupCall: true
validateButtonText: qsTr("Lancer")
onReturnRequested: listStackView.pop()
onValidateRequested: {
if (groupName.length === 0) {
UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("Un nom doit être donné à l'appel de groupe"), false)
} else {
mainItem.confInfoGui.core.subject = groupName
mainItem.confInfoGui.core.isScheduled = false
mainItem.confInfoGui.core.addParticipants(selectedParticipants)
mainItem.confInfoGui.core.save()
}
}
}
// }
}
} }
Component{ Component{

View file

@ -331,14 +331,13 @@ AbstractMainPage {
background: Item{} background: Item{}
Layout.preferredWidth: 24 * DefaultStyle.dp Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp Layout.preferredHeight: 24 * DefaultStyle.dp
property var callObj
icon.source: AppIcons.phone icon.source: AppIcons.phone
width: 24 * DefaultStyle.dp width: 24 * DefaultStyle.dp
height: 24 * DefaultStyle.dp height: 24 * DefaultStyle.dp
icon.width: 24 * DefaultStyle.dp icon.width: 24 * DefaultStyle.dp
icon.height: 24 * DefaultStyle.dp icon.height: 24 * DefaultStyle.dp
onClicked: { onClicked: {
callObj = UtilsCpp.createCall(modelData.address) UtilsCpp.createCall(modelData.address)
} }
} }
} }

View file

@ -275,6 +275,10 @@ AbstractMainPage {
onReturnRequested: { onReturnRequested: {
container.pop() container.pop()
} }
onValidateRequested: {
conferenceInfoGui.core.resetParticipants(addParticipantLayout.selectedParticipants)
returnRequested()
}
} }
} }
Component { Component {
@ -379,9 +383,8 @@ AbstractMainPage {
inversedColors: true inversedColors: true
color: DefaultStyle.main2_600 color: DefaultStyle.main2_600
background: Item{} background: Item{}
property var callObj
onClicked: { onClicked: {
callObj = UtilsCpp.createCall(mainItem.selectedConference.core.uri) UtilsCpp.createCall(mainItem.selectedConference.core.uri)
} }
} }
Button { Button {

View file

@ -5,13 +5,12 @@ import Linphone
import UtilsCpp 1.0 import UtilsCpp 1.0
// Snippet // Snippet
Window{ Window {
id: mainItem id: mainItem
height: 400 height: 400
width: 800 width: 800
onWidthChanged: console.log(width) onWidthChanged: console.log(width)
property var callVarObject property var call
property var call: callVarObject ? callVarObject.value : null
property var callState: call && call.core.state property var callState: call && call.core.state
onCallStateChanged: { onCallStateChanged: {
console.log("State:" +callState) console.log("State:" +callState)
@ -138,7 +137,7 @@ Window{
onClicked: { onClicked: {
var address = usernameToCall.text + "@sip.linphone.org" var address = usernameToCall.text + "@sip.linphone.org"
console.log("Calling "+address) console.log("Calling "+address)
mainItem.callVarObject = UtilsCpp.createCall(address) UtilsCpp.createCall(address)
proto.component1 = comp proto.component1 = comp
} }
} }