Delete/cancel conference, Conference Info, icons, meeting list, waiting room, settings panel, video device

This commit is contained in:
Gaelle Braud 2024-03-19 12:38:59 +01:00 committed by Julien Wadel
parent 1ed1f39113
commit 2770076a44
52 changed files with 1139 additions and 682 deletions

View file

@ -287,7 +287,10 @@ QQuickWindow *App::getCallsWindow(QVariant callGui) {
} }
qInfo() << log().arg("Subwindow status: `%1`.").arg(component.status()); qInfo() << log().arg("Subwindow status: `%1`.").arg(component.status());
QObject *object = component.createWithInitialProperties({{"call", callGui}}); QObject *object = nullptr;
// if (!callGui.isNull() && callGui.isValid()) object = component.createWithInitialProperties({{"call",
// callGui}});
object = component.create();
Q_ASSERT(object); Q_ASSERT(object);
if (!object) { if (!object) {
qCritical() << log().arg("Calls window could not be created."); qCritical() << log().arg("Calls window could not be created.");
@ -306,10 +309,14 @@ QQuickWindow *App::getCallsWindow(QVariant callGui) {
// window->setParent(mMainWindow); // window->setParent(mMainWindow);
mCallsWindow = window; mCallsWindow = window;
} }
mCallsWindow->setProperty("call", callGui); if (!callGui.isNull() && callGui.isValid()) mCallsWindow->setProperty("call", callGui);
return mCallsWindow; return mCallsWindow;
} }
void App::setCallsWindowProperty(const char *id, QVariant property) {
if (mCallsWindow) mCallsWindow->setProperty(id, property);
}
void App::closeCallsWindow() { void App::closeCallsWindow() {
if (mCallsWindow) { if (mCallsWindow) {
mCallsWindow->close(); mCallsWindow->close();

View file

@ -93,6 +93,7 @@ public:
void onLoggerInitialized(); void onLoggerInitialized();
QQuickWindow *getCallsWindow(QVariant callGui); QQuickWindow *getCallsWindow(QVariant callGui);
void setCallsWindowProperty(const char *id, QVariant property);
void closeCallsWindow(); void closeCallsWindow();
QQuickWindow *getMainWindow(); QQuickWindow *getMainWindow();

View file

@ -39,7 +39,7 @@ ConferenceCore::ConferenceCore(const std::shared_ptr<linphone::Conference> &conf
} }
ConferenceCore::~ConferenceCore() { ConferenceCore::~ConferenceCore() {
mustBeInMainThread("~" + getClassName()); mustBeInMainThread("~" + getClassName());
emit mConferenceModel->removeListener(); if (mConferenceModel) emit mConferenceModel->removeListener();
} }
void ConferenceCore::setSelf(QSharedPointer<ConferenceCore> me) { void ConferenceCore::setSelf(QSharedPointer<ConferenceCore> me) {

View file

@ -101,6 +101,7 @@ ConferenceInfoCore::ConferenceInfoCore(std::shared_ptr<linphone::ConferenceInfo>
}); });
} }
connect(this, &ConferenceInfoCore::dateTimeChanged, [this] { setDuration(mDateTime.secsTo(mEndDateTime) / 60.0); });
connect(this, &ConferenceInfoCore::endDateTimeChanged, connect(this, &ConferenceInfoCore::endDateTimeChanged,
[this] { setDuration(mDateTime.secsTo(mEndDateTime) / 60.0); }); [this] { setDuration(mDateTime.secsTo(mEndDateTime) / 60.0); });
connect(this, &ConferenceInfoCore::durationChanged, [this] { setEndDateTime(mDateTime.addSecs(mDuration * 60)); }); connect(this, &ConferenceInfoCore::durationChanged, [this] { setEndDateTime(mDateTime.addSecs(mDuration * 60)); });
@ -168,15 +169,27 @@ void ConferenceInfoCore::setSelf(QSharedPointer<ConferenceInfoCore> me) {
setIsEnded(computeIsEnded()); setIsEnded(computeIsEnded());
}); });
}); });
mConfInfoModelConnection->makeConnectToCore(&ConferenceInfoCore::lDeleteConferenceInfo, mConfInfoModelConnection->makeConnectToCore(&ConferenceInfoCore::lCancelConferenceInfo, [this]() {
[this]() { mConferenceInfoModel->deleteConferenceInfo(); }); mConfInfoModelConnection->invokeToModel([this] {
if (Utils::isMe(mOrganizerAddress)) {
mConferenceInfoModel->cancelConference();
}
});
});
mConfInfoModelConnection->makeConnectToCore(&ConferenceInfoCore::lDeleteConferenceInfo, [this]() {
mConfInfoModelConnection->invokeToModel([this] { mConferenceInfoModel->deleteConferenceInfo(); });
});
mConfInfoModelConnection->makeConnectToModel(&ConferenceInfoModel::conferenceInfoDeleted, mConfInfoModelConnection->makeConnectToModel(&ConferenceInfoModel::conferenceInfoDeleted,
&ConferenceInfoCore::removed); &ConferenceInfoCore::removed);
mConfInfoModelConnection->makeConnectToModel( mConfInfoModelConnection->makeConnectToModel(
&ConferenceInfoModel::schedulerStateChanged, [this](linphone::ConferenceScheduler::State state) { &ConferenceInfoModel::schedulerStateChanged, [this](linphone::ConferenceScheduler::State state) {
mConfInfoModelConnection->invokeToCore( auto confInfoState = mConferenceInfoModel->getState();
[this, state = LinphoneEnums::fromLinphone(state)] { setConferenceSchedulerState(state); }); mConfInfoModelConnection->invokeToCore([this, state = LinphoneEnums::fromLinphone(state),
infoState = LinphoneEnums::fromLinphone(confInfoState)] {
setConferenceSchedulerState(state);
setConferenceInfoState(infoState);
});
}); });
mConfInfoModelConnection->makeConnectToModel( mConfInfoModelConnection->makeConnectToModel(
&ConferenceInfoModel::invitationsSent, &ConferenceInfoModel::invitationsSent,
@ -190,7 +203,14 @@ void ConferenceInfoCore::setSelf(QSharedPointer<ConferenceInfoCore> me) {
} }
} }
//------------------------------------------------------------------------------------------------ QString ConferenceInfoCore::getStartEndDateString() {
if (Utils::datesAreEqual(mDateTime.date(), mEndDateTime.date())) {
return QLocale().toString(mDateTime, "ddd d MMM - hh") + "h - " + QLocale().toString(mEndDateTime, "hh") + "h";
} else {
return QLocale().toString(mDateTime, "ddd d MMM - hh") + "h - " +
QLocale().toString(mEndDateTime, "ddd d MMM - hh") + "h";
}
}
// Note conferenceInfo->getDateTime uses UTC // Note conferenceInfo->getDateTime uses UTC
QDateTime ConferenceInfoCore::getDateTimeUtc() const { QDateTime ConferenceInfoCore::getDateTimeUtc() const {
@ -492,6 +512,7 @@ void ConferenceInfoCore::save() {
mustBeInLinphoneThread(getClassName() + "::save()"); mustBeInLinphoneThread(getClassName() + "::save()");
thisCopy->writeIntoModel(mConferenceInfoModel); thisCopy->writeIntoModel(mConferenceInfoModel);
thisCopy->deleteLater(); thisCopy->deleteLater();
mConferenceInfoModel->updateConferenceInfo();
}); });
} else { } else {
mCoreModelConnection->invokeToModel([this, thisCopy]() { mCoreModelConnection->invokeToModel([this, thisCopy]() {
@ -545,11 +566,6 @@ void ConferenceInfoCore::undo() {
} }
} }
void ConferenceInfoCore::cancelConference() {
if (!mConferenceInfoModel) return;
mConferenceInfoModel->cancelConference();
}
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
// void ConferenceInfoCore::createConference(const int &securityLevel) { // void ConferenceInfoCore::createConference(const int &securityLevel) {

View file

@ -96,6 +96,7 @@ public:
LinphoneEnums::ConferenceInfoState getConferenceInfoState() const; LinphoneEnums::ConferenceInfoState getConferenceInfoState() const;
LinphoneEnums::ConferenceSchedulerState getConferenceSchedulerState() const; LinphoneEnums::ConferenceSchedulerState getConferenceSchedulerState() const;
// LinphoneEnums::ConferenceSchedulerState getConferenceSchedulerState() const; // LinphoneEnums::ConferenceSchedulerState getConferenceSchedulerState() const;
QString toStartEndDateString();
void setDateTime(const QDateTime &date); void setDateTime(const QDateTime &date);
void setEndDateTime(const QDateTime &date); void setEndDateTime(const QDateTime &date);
@ -118,12 +119,12 @@ public:
void resetParticipants(QVariantList participants); void resetParticipants(QVariantList participants);
Q_INVOKABLE void resetParticipants(const QStringList &adresses); Q_INVOKABLE void resetParticipants(const QStringList &adresses);
Q_INVOKABLE int getParticipantIndex(const QString &address); Q_INVOKABLE int getParticipantIndex(const QString &address);
Q_INVOKABLE QString getStartEndDateString();
void writeFromModel(const std::shared_ptr<ConferenceInfoModel> &model); void writeFromModel(const std::shared_ptr<ConferenceInfoModel> &model);
void writeIntoModel(std::shared_ptr<ConferenceInfoModel> model); void writeIntoModel(std::shared_ptr<ConferenceInfoModel> model);
Q_INVOKABLE void save(); Q_INVOKABLE void save();
Q_INVOKABLE void cancelConference();
Q_INVOKABLE void undo(); Q_INVOKABLE void undo();
// Tools // Tools
@ -158,7 +159,7 @@ signals:
void removed(); void removed();
// void lCreateConference(const int &securityLevel); // void lCreateConference(const int &securityLevel);
// void lCancelConference(); void lCancelConferenceInfo();
void lDeleteConferenceInfo(); // Remove completly this conference info from DB void lDeleteConferenceInfo(); // Remove completly this conference info from DB
private: private:

View file

@ -25,13 +25,13 @@
DEFINE_ABSTRACT_OBJECT(ConferenceInfoGui) DEFINE_ABSTRACT_OBJECT(ConferenceInfoGui)
ConferenceInfoGui::ConferenceInfoGui() { ConferenceInfoGui::ConferenceInfoGui() {
qDebug() << "[ConferenceInfoGui] new" << this; // qDebug() << "[ConferenceInfoGui] new" << this;
mCore = ConferenceInfoCore::create(nullptr); mCore = ConferenceInfoCore::create(nullptr);
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
if (isInLinphoneThread()) moveToThread(App::getInstance()->thread()); if (isInLinphoneThread()) moveToThread(App::getInstance()->thread());
} }
ConferenceInfoGui::ConferenceInfoGui(QSharedPointer<ConferenceInfoCore> core) { ConferenceInfoGui::ConferenceInfoGui(QSharedPointer<ConferenceInfoCore> core) {
qDebug() << "[ConferenceInfoGui] new" << this; // qDebug() << "[ConferenceInfoGui] new" << this;
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
mCore = core; mCore = core;
if (isInLinphoneThread()) moveToThread(App::getInstance()->thread()); if (isInLinphoneThread()) moveToThread(App::getInstance()->thread());
@ -39,7 +39,7 @@ ConferenceInfoGui::ConferenceInfoGui(QSharedPointer<ConferenceInfoCore> core) {
ConferenceInfoGui::~ConferenceInfoGui() { ConferenceInfoGui::~ConferenceInfoGui() {
mustBeInMainThread("~" + getClassName()); mustBeInMainThread("~" + getClassName());
qDebug() << "[ConferenceInfoGui] delete" << this; // qDebug() << "[ConferenceInfoGui] delete" << this;
} }
ConferenceInfoCore *ConferenceInfoGui::getCore() const { ConferenceInfoCore *ConferenceInfoGui::getCore() const {

View file

@ -88,6 +88,7 @@ void ConferenceInfoList::setSelf(QSharedPointer<ConferenceInfoList> me) {
// qWarning() << "No ConferenceInfo have beend found for " << conferenceInfo->getUri()->asString().c_str(); // qWarning() << "No ConferenceInfo have beend found for " << conferenceInfo->getUri()->asString().c_str();
// }); // });
mCoreModelConnection->makeConnectToModel(&CoreModel::defaultAccountChanged, &ConferenceInfoList::lUpdate);
mCoreModelConnection->makeConnectToModel(&CoreModel::conferenceInfoReceived, &ConferenceInfoList::lUpdate); mCoreModelConnection->makeConnectToModel(&CoreModel::conferenceInfoReceived, &ConferenceInfoList::lUpdate);
mCoreModelConnection->makeConnectToModel(&CoreModel::conferenceStateChanged, [this] { mCoreModelConnection->makeConnectToModel(&CoreModel::conferenceStateChanged, [this] {
qDebug() << "list: conf state changed"; qDebug() << "list: conf state changed";

View file

@ -29,6 +29,7 @@ ConferenceInfoProxy::ConferenceInfoProxy(QObject *parent) : SortFilterProxy(pare
mList = ConferenceInfoList::create(); mList = ConferenceInfoList::create();
setSourceModel(mList.get()); setSourceModel(mList.get());
connect(this, &ConferenceInfoProxy::searchTextChanged, [this] { invalidate(); }); connect(this, &ConferenceInfoProxy::searchTextChanged, [this] { invalidate(); });
connect(this, &ConferenceInfoProxy::lUpdate, mList.get(), &ConferenceInfoList::lUpdate);
} }
ConferenceInfoProxy::~ConferenceInfoProxy() { ConferenceInfoProxy::~ConferenceInfoProxy() {

View file

@ -44,6 +44,7 @@ protected:
signals: signals:
void searchTextChanged(); void searchTextChanged();
void lUpdate();
private: private:
QString mSearchText; QString mSearchText;

View file

@ -71,6 +71,10 @@ void Settings::setSelf(QSharedPointer<Settings> me) {
mSettingsModelConnection->invokeToModel( mSettingsModelConnection->invokeToModel(
[this, id]() { mSettingsModel->setVideoDevice(Utils::appStringToCoreString(id)); }); [this, id]() { mSettingsModel->setVideoDevice(Utils::appStringToCoreString(id)); });
}); });
mSettingsModelConnection->makeConnectToModel(&SettingsModel::videoDeviceChanged, [this](const std::string &id) {
mSettingsModelConnection->invokeToModel(
[this, id = Utils::coreStringToAppString(id)]() { setCurrentVideoDevice(id); });
});
} }
QString Settings::getConfigPath(const QCommandLineParser &parser) { QString Settings::getConfigPath(const QCommandLineParser &parser) {
@ -97,6 +101,23 @@ QStringList Settings::getVideoDevicesList() const {
return mVideoDevices; return mVideoDevices;
} }
void Settings::setCurrentVideoDevice(const QString &id) {
if (mCurrentVideoDeviceId != id) {
mCurrentVideoDeviceId = id;
emit videoDeviceChanged();
}
}
int Settings::getCurrentVideoDeviceIndex() {
auto found = std::find_if(mVideoDevices.begin(), mVideoDevices.end(),
[this](const QString &device) { return mCurrentVideoDeviceId == device; });
if (found != mVideoDevices.end()) {
auto index = std::distance(mVideoDevices.begin(), found);
return index;
}
return -1;
}
bool Settings::getFirstLaunch() const { bool Settings::getFirstLaunch() const {
auto val = mAppSettings.value("firstLaunch", 1).toInt(); auto val = mAppSettings.value("firstLaunch", 1).toInt();
return val; return val;

View file

@ -34,6 +34,7 @@ class Settings : public QObject, public AbstractObject {
Q_PROPERTY(QStringList inputAudioDevicesList READ getInputAudioDevicesList NOTIFY inputAudioDeviceChanged) Q_PROPERTY(QStringList inputAudioDevicesList READ getInputAudioDevicesList NOTIFY inputAudioDeviceChanged)
Q_PROPERTY(QStringList outputAudioDevicesList READ getOutputAudioDevicesList NOTIFY outputAudioDeviceChanged) Q_PROPERTY(QStringList outputAudioDevicesList READ getOutputAudioDevicesList NOTIFY outputAudioDeviceChanged)
Q_PROPERTY(QStringList videoDevicesList READ getVideoDevicesList NOTIFY videoDeviceChanged) Q_PROPERTY(QStringList videoDevicesList READ getVideoDevicesList NOTIFY videoDeviceChanged)
Q_PROPERTY(int currentVideoDeviceIndex READ getCurrentVideoDeviceIndex NOTIFY videoDeviceChanged)
public: public:
static QSharedPointer<Settings> create(); static QSharedPointer<Settings> create();
Settings(QObject *parent = Q_NULLPTR); Settings(QObject *parent = Q_NULLPTR);
@ -49,6 +50,9 @@ public:
QStringList getVideoDevicesList() const; QStringList getVideoDevicesList() const;
void setCurrentVideoDevice(const QString &id);
int getCurrentVideoDeviceIndex();
Q_INVOKABLE void setFirstLaunch(bool first); Q_INVOKABLE void setFirstLaunch(bool first);
Q_INVOKABLE bool getFirstLaunch() const; Q_INVOKABLE bool getFirstLaunch() const;
@ -64,6 +68,7 @@ signals:
private: private:
std::shared_ptr<SettingsModel> mSettingsModel; std::shared_ptr<SettingsModel> mSettingsModel;
QStringList mInputAudioDevices; QStringList mInputAudioDevices;
QString mCurrentVideoDeviceId;
QStringList mOutputAudioDevices; QStringList mOutputAudioDevices;
QStringList mVideoDevices; QStringList mVideoDevices;
QSettings mAppSettings; QSettings mAppSettings;

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="M160,112a24,24,0,1,1-24-24A24,24,0,0,1,160,112Zm64-72V216a16,16,0,0,1-16,16H64a16,16,0,0,1-16-16V192H32a8,8,0,0,1,0-16H48V136H32a8,8,0,0,1,0-16H48V80H32a8,8,0,0,1,0-16H48V40A16,16,0,0,1,64,24H208A16,16,0,0,1,224,40ZM190.4,163.2A67.88,67.88,0,0,0,163,141.51a40,40,0,1,0-53.94,0A67.88,67.88,0,0,0,81.6,163.2a8,8,0,1,0,12.8,9.6,52,52,0,0,1,83.2,0,8,8,0,1,0,12.8-9.6Z"></path></svg>

After

Width:  |  Height:  |  Size: 487 B

View file

@ -1,17 +0,0 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_4435_19461)">
<path d="M23.42 18.4615C23.42 18.918 23.2863 19.3641 23.0358 19.7436C22.7852 20.1231 22.4291 20.4189 22.0125 20.5936C21.5959 20.7682 21.1375 20.8139 20.6952 20.7249C20.2529 20.6358 19.8467 20.4161 19.5278 20.0933C19.2089 19.7706 18.9918 19.3594 18.9038 18.9117C18.8158 18.4641 18.861 18.0001 19.0336 17.5784C19.2061 17.1567 19.4984 16.7963 19.8733 16.5428C20.2482 16.2892 20.6891 16.1538 21.14 16.1538C21.7447 16.1538 22.3246 16.397 22.7522 16.8298C23.1798 17.2625 23.42 17.8495 23.42 18.4615ZM29.5 11.5385V28.4615C29.5 28.8696 29.3399 29.2609 29.0548 29.5494C28.7697 29.8379 28.3831 30 27.98 30H14.3C13.8969 30 13.5103 29.8379 13.2252 29.5494C12.9401 29.2609 12.78 28.8696 12.78 28.4615V26.1538H11.26C11.0584 26.1538 10.8651 26.0728 10.7226 25.9285C10.5801 25.7843 10.5 25.5886 10.5 25.3846C10.5 25.1806 10.5801 24.9849 10.7226 24.8407C10.8651 24.6964 11.0584 24.6154 11.26 24.6154H12.78V20.7692H11.26C11.0584 20.7692 10.8651 20.6882 10.7226 20.5439C10.5801 20.3997 10.5 20.204 10.5 20C10.5 19.796 10.5801 19.6003 10.7226 19.4561C10.8651 19.3118 11.0584 19.2308 11.26 19.2308H12.78V15.3846H11.26C11.0584 15.3846 10.8651 15.3036 10.7226 15.1593C10.5801 15.0151 10.5 14.8194 10.5 14.6154C10.5 14.4114 10.5801 14.2157 10.7226 14.0715C10.8651 13.9272 11.0584 13.8462 11.26 13.8462H12.78V11.5385C12.78 11.1304 12.9401 10.7391 13.2252 10.4506C13.5103 10.1621 13.8969 10 14.3 10H27.98C28.3831 10 28.7697 10.1621 29.0548 10.4506C29.3399 10.7391 29.5 11.1304 29.5 11.5385ZM26.308 23.3846C25.635 22.4714 24.7376 21.7524 23.705 21.299C24.2709 20.7761 24.6674 20.0922 24.8424 19.3371C25.0174 18.582 24.9628 17.791 24.6857 17.0679C24.4086 16.3448 23.922 15.7234 23.2898 15.2852C22.6575 14.847 21.9091 14.6125 21.1428 14.6125C20.3766 14.6125 19.6282 14.847 18.9959 15.2852C18.3637 15.7234 17.8771 16.3448 17.6 17.0679C17.3229 17.791 17.2683 18.582 17.4433 19.3371C17.6183 20.0922 18.0148 20.7761 18.5807 21.299C17.546 21.7515 16.6465 22.4706 15.972 23.3846C15.9121 23.4654 15.8685 23.5574 15.8438 23.6552C15.819 23.7531 15.8135 23.8549 15.8276 23.9549C15.8418 24.0549 15.8752 24.1511 15.926 24.2381C15.9769 24.325 16.0442 24.4009 16.124 24.4615C16.2038 24.5221 16.2947 24.5662 16.3914 24.5913C16.4881 24.6164 16.5887 24.6219 16.6875 24.6077C16.7863 24.5934 16.8813 24.5595 16.9672 24.5081C17.0531 24.4566 17.1281 24.3885 17.188 24.3077C17.6481 23.6867 18.2448 23.1827 18.9308 22.8356C19.6167 22.4884 20.3731 22.3077 21.14 22.3077C21.9069 22.3077 22.6633 22.4884 23.3492 22.8356C24.0352 23.1827 24.6319 23.6867 25.092 24.3077C25.2129 24.4709 25.393 24.5788 25.5925 24.6077C25.7921 24.6365 25.9947 24.5839 26.156 24.4615C26.3173 24.3391 26.4239 24.1569 26.4524 23.9549C26.4809 23.753 26.4289 23.5478 26.308 23.3846Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_4435_19461" x="0.5" y="0" width="39" height="40" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4435_19461"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4435_19461" result="shape"/>
</filter>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24.7075 8.70751L10.4137 23H21C21.2652 23 21.5196 23.1054 21.7071 23.2929C21.8946 23.4804 22 23.7348 22 24C22 24.2652 21.8946 24.5196 21.7071 24.7071C21.5196 24.8947 21.2652 25 21 25H8C7.73478 25 7.48043 24.8947 7.29289 24.7071C7.10536 24.5196 7 24.2652 7 24V11C7 10.7348 7.10536 10.4804 7.29289 10.2929C7.48043 10.1054 7.73478 10 8 10C8.26522 10 8.51957 10.1054 8.70711 10.2929C8.89464 10.4804 9 10.7348 9 11V21.5863L23.2925 7.29251C23.3854 7.1996 23.4957 7.1259 23.6171 7.07561C23.7385 7.02533 23.8686 6.99945 24 6.99945C24.1314 6.99945 24.2615 7.02533 24.3829 7.07561C24.5043 7.1259 24.6146 7.1996 24.7075 7.29251C24.8004 7.38542 24.8741 7.49572 24.9244 7.61711C24.9747 7.7385 25.0006 7.86861 25.0006 8.00001C25.0006 8.1314 24.9747 8.26151 24.9244 8.3829C24.8741 8.5043 24.8004 8.6146 24.7075 8.70751Z" fill="#343330"/>
</svg>

After

Width:  |  Height:  |  Size: 935 B

View file

@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M29.7075 12.7075L17.7075 24.7075C17.6146 24.8005 17.5043 24.8742 17.3829 24.9246C17.2615 24.9749 17.1314 25.0008 17 25.0008C16.8686 25.0008 16.7385 24.9749 16.6171 24.9246C16.4957 24.8742 16.3854 24.8005 16.2925 24.7075L4 12.4137V19C4 19.2652 3.89464 19.5196 3.70711 19.7071C3.51957 19.8946 3.26522 20 3 20C2.73478 20 2.48043 19.8946 2.29289 19.7071C2.10536 19.5196 2 19.2652 2 19V10C2 9.73478 2.10536 9.48043 2.29289 9.29289C2.48043 9.10536 2.73478 9 3 9H12C12.2652 9 12.5196 9.10536 12.7071 9.29289C12.8946 9.48043 13 9.73478 13 10C13 10.2652 12.8946 10.5196 12.7071 10.7071C12.5196 10.8946 12.2652 11 12 11H5.41375L17 22.5863L28.2925 11.2925C28.3854 11.1996 28.4957 11.1259 28.6171 11.0756C28.7385 11.0253 28.8686 10.9994 29 10.9994C29.1314 10.9994 29.2615 11.0253 29.3829 11.0756C29.5043 11.1259 29.6146 11.1996 29.7075 11.2925C29.8004 11.3854 29.8741 11.4957 29.9244 11.6171C29.9747 11.7385 30.0006 11.8686 30.0006 12C30.0006 12.1314 29.9747 12.2615 29.9244 12.3829C29.8741 12.5043 29.8004 12.6146 29.7075 12.7075Z" fill="#343330"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M25 8V21C25 21.2652 24.8947 21.5196 24.7071 21.7071C24.5196 21.8946 24.2652 22 24 22C23.7348 22 23.4804 21.8946 23.2929 21.7071C23.1054 21.5196 23 21.2652 23 21V10.4137L8.70751 24.7075C8.51987 24.8951 8.26537 25.0006 8.00001 25.0006C7.73464 25.0006 7.48015 24.8951 7.29251 24.7075C7.10487 24.5199 6.99945 24.2654 6.99945 24C6.99945 23.7346 7.10487 23.4801 7.29251 23.2925L21.5863 9H11C10.7348 9 10.4804 8.89464 10.2929 8.70711C10.1054 8.51957 10 8.26522 10 8C10 7.73478 10.1054 7.48043 10.2929 7.29289C10.4804 7.10536 10.7348 7 11 7H24C24.2652 7 24.5196 7.10536 24.7071 7.29289C24.8947 7.48043 25 7.73478 25 8Z" fill="#343330"/>
</svg>

After

Width:  |  Height:  |  Size: 741 B

View file

@ -0,0 +1,3 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 40C17.2667 40 14.6833 39.475 12.25 38.425C9.81667 37.375 7.69167 35.9417 5.875 34.125C4.05833 32.3083 2.625 30.1833 1.575 27.75C0.525 25.3167 0 22.7333 0 20C0 17.2333 0.525 14.6417 1.575 12.225C2.625 9.80833 4.05833 7.69167 5.875 5.875C7.69167 4.05833 9.81667 2.625 12.25 1.575C14.6833 0.525 17.2667 0 20 0C20.5667 0 21.0417 0.191667 21.425 0.575C21.8083 0.958333 22 1.43333 22 2C22 2.56667 21.8083 3.04167 21.425 3.425C21.0417 3.80833 20.5667 4 20 4C15.5667 4 11.7917 5.55833 8.675 8.675C5.55833 11.7917 4 15.5667 4 20C4 24.4333 5.55833 28.2083 8.675 31.325C11.7917 34.4417 15.5667 36 20 36C24.4333 36 28.2083 34.4417 31.325 31.325C34.4417 28.2083 36 24.4333 36 20C36 19.4333 36.1917 18.9583 36.575 18.575C36.9583 18.1917 37.4333 18 38 18C38.5667 18 39.0417 18.1917 39.425 18.575C39.8083 18.9583 40 19.4333 40 20C40 22.7333 39.475 25.3167 38.425 27.75C37.375 30.1833 35.9417 32.3083 34.125 34.125C32.3083 35.9417 30.1917 37.375 27.775 38.425C25.3583 39.475 22.7667 40 20 40Z" fill="#FE5E00"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

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="M132,24A100.11,100.11,0,0,0,32,124v84.33A15.69,15.69,0,0,0,47.67,224H132a100,100,0,0,0,0-200Zm28,128H96a8,8,0,0,1,0-16h64a8,8,0,0,1,0,16Zm0-32H96a8,8,0,0,1,0-16h64a8,8,0,0,1,0,16Z"></path></svg>

After

Width:  |  Height:  |  Size: 303 B

View file

@ -1,17 +0,0 @@
<svg width="38" height="39" viewBox="0 0 38 39" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_4441_27383)">
<path d="M19 10C16.6139 10.0027 14.3262 10.9913 12.6389 12.7489C10.9517 14.5065 10.0026 16.8894 10 19.375V27.2809C10.0005 27.6704 10.1492 28.0438 10.4136 28.3192C10.678 28.5946 11.0364 28.7495 11.4103 28.75H19C21.3869 28.75 23.6761 27.7623 25.364 26.0041C27.0518 24.246 28 21.8614 28 19.375C28 16.8886 27.0518 14.504 25.364 12.7459C23.6761 10.9877 21.3869 10 19 10ZM21.52 22H15.76C15.569 22 15.3859 21.921 15.2509 21.7803C15.1159 21.6397 15.04 21.4489 15.04 21.25C15.04 21.0511 15.1159 20.8603 15.2509 20.7197C15.3859 20.579 15.569 20.5 15.76 20.5H21.52C21.711 20.5 21.8941 20.579 22.0291 20.7197C22.1641 20.8603 22.24 21.0511 22.24 21.25C22.24 21.4489 22.1641 21.6397 22.0291 21.7803C21.8941 21.921 21.711 22 21.52 22ZM21.52 19H15.76C15.569 19 15.3859 18.921 15.2509 18.7803C15.1159 18.6397 15.04 18.4489 15.04 18.25C15.04 18.0511 15.1159 17.8603 15.2509 17.7197C15.3859 17.579 15.569 17.5 15.76 17.5H21.52C21.711 17.5 21.8941 17.579 22.0291 17.7197C22.1641 17.8603 22.24 18.0511 22.24 18.25C22.24 18.4489 22.1641 18.6397 22.0291 18.7803C21.8941 18.921 21.711 19 21.52 19Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_4441_27383" x="0" y="0" width="38" height="38.75" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4441_27383"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4441_27383" result="shape"/>
</filter>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -1,3 +0,0 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path id="Shape" d="M11 12C11.5523 12 12 11.5523 12 11C12 10.4477 11.5523 10 11 10L3.41421 10L11.7071 1.70711C12.0976 1.31658 12.0976 0.683418 11.7071 0.292894C11.3166 -0.0976296 10.6834 -0.0976297 10.2929 0.292894L2 8.58579L2 1C2 0.447715 1.55229 4.0306e-08 1 -7.97631e-09C0.447715 -5.62586e-08 -8.97416e-07 0.447715 -9.45698e-07 1L-1.81993e-06 11C-1.86821e-06 11.5523 0.447714 12 0.999999 12L11 12Z" fill="#4FAE80"/>
</svg>

Before

Width:  |  Height:  |  Size: 522 B

View file

@ -1,3 +0,0 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path id="Shape" d="M11 12C11.5523 12 12 11.5523 12 11C12 10.4477 11.5523 10 11 10L3.41421 10L11.7071 1.70711C12.0976 1.31658 12.0976 0.683418 11.7071 0.292894C11.3166 -0.0976296 10.6834 -0.0976297 10.2929 0.292894L2 8.58579L2 1C2 0.447715 1.55229 4.0306e-08 1 -7.97631e-09C0.447715 -5.62586e-08 -8.97416e-07 0.447715 -9.45698e-07 1L-1.81993e-06 11C-1.86821e-06 11.5523 0.447714 12 0.999999 12L11 12Z" fill="#DD5F5F"/>
</svg>

Before

Width:  |  Height:  |  Size: 522 B

View file

@ -1,3 +0,0 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path id="Shape" d="M1 0C0.447715 0 1.49012e-08 0.447715 1.49012e-08 1C1.49012e-08 1.55228 0.447715 2 1 2H8.58579L0.292893 10.2929C-0.0976311 10.6834 -0.0976311 11.3166 0.292893 11.7071C0.683417 12.0976 1.31658 12.0976 1.70711 11.7071L10 3.41421V11C10 11.5523 10.4477 12 11 12C11.5523 12 12 11.5523 12 11V1C12 0.447715 11.5523 0 11 0H1Z" fill="#4AA8FF"/>
</svg>

Before

Width:  |  Height:  |  Size: 458 B

View file

@ -1,3 +0,0 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path id="Shape" d="M1 0C0.447715 0 1.49012e-08 0.447715 1.49012e-08 1C1.49012e-08 1.55228 0.447715 2 1 2H8.58579L0.292893 10.2929C-0.0976311 10.6834 -0.0976311 11.3166 0.292893 11.7071C0.683417 12.0976 1.31658 12.0976 1.70711 11.7071L10 3.41421V11C10 11.5523 10.4477 12 11 12C11.5523 12 12 11.5523 12 11V1C12 0.447715 11.5523 0 11 0H1Z" fill="#DD5F5F"/>
</svg>

Before

Width:  |  Height:  |  Size: 458 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="M231.88,175.08A56.26,56.26,0,0,1,176,224C96.6,224,32,159.4,32,80A56.26,56.26,0,0,1,80.92,24.12a16,16,0,0,1,16.62,9.52l21.12,47.15,0,.12A16,16,0,0,1,117.39,96c-.18.27-.37.52-.57.77L96,121.45c7.49,15.22,23.41,31,38.83,38.51l24.34-20.71a8.12,8.12,0,0,1,.75-.56,16,16,0,0,1,15.17-1.4l.13.06,47.11,21.11A16,16,0,0,1,231.88,175.08Z"></path></svg>

After

Width:  |  Height:  |  Size: 449 B

View file

@ -1,17 +0,0 @@
<svg width="38" height="38" viewBox="0 0 38 38" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_4432_11261)">
<path d="M27.9895 23.5972C27.829 24.8168 27.2301 25.9362 26.3046 26.7465C25.3791 27.5567 24.1903 28.0023 22.9602 28.0001C15.8141 28.0001 10 22.186 10 15.0399C9.9978 13.8098 10.4434 12.621 11.2537 11.6955C12.0639 10.77 13.1833 10.1711 14.4029 10.0106C14.7113 9.97296 15.0236 10.0361 15.2932 10.1905C15.5628 10.3449 15.7752 10.5824 15.8987 10.8674L17.7995 15.111V15.1218C17.8941 15.34 17.9332 15.5783 17.9132 15.8152C17.8933 16.0522 17.815 16.2806 17.6852 16.4799C17.669 16.5042 17.6519 16.5267 17.6339 16.5492L15.7601 18.7705C16.4342 20.1403 17.867 21.5605 19.2549 22.2364L21.4455 20.3725C21.467 20.3544 21.4896 20.3376 21.513 20.3221C21.7122 20.1893 21.9413 20.1082 22.1797 20.0862C22.4181 20.0642 22.6582 20.1019 22.8783 20.1961L22.89 20.2015L27.13 22.1014C27.4156 22.2245 27.6536 22.4368 27.8086 22.7064C27.9635 22.976 28.027 23.2885 27.9895 23.5972Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_4432_11261" x="0" y="0" width="38" height="38" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4432_11261"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4432_11261" result="shape"/>
</filter>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.5 KiB

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="M64.12,147.8a4,4,0,0,1-4,4.2H16a8,8,0,0,1-7.8-6.17,8.35,8.35,0,0,1,1.62-6.93A67.79,67.79,0,0,1,37,117.51a40,40,0,1,1,66.46-35.8,3.94,3.94,0,0,1-2.27,4.18A64.08,64.08,0,0,0,64,144C64,145.28,64,146.54,64.12,147.8Zm182-8.91A67.76,67.76,0,0,0,219,117.51a40,40,0,1,0-66.46-35.8,3.94,3.94,0,0,0,2.27,4.18A64.08,64.08,0,0,1,192,144c0,1.28,0,2.54-.12,3.8a4,4,0,0,0,4,4.2H240a8,8,0,0,0,7.8-6.17A8.33,8.33,0,0,0,246.17,138.89Zm-89,43.18a48,48,0,1,0-58.37,0A72.13,72.13,0,0,0,65.07,212,8,8,0,0,0,72,224H184a8,8,0,0,0,6.93-12A72.15,72.15,0,0,0,157.19,182.07Z"></path></svg>

After

Width:  |  Height:  |  Size: 670 B

View file

@ -1,17 +0,0 @@
<svg width="40" height="36" viewBox="0 0 40 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_4441_41328)">
<path d="M14.676 18.9716C14.6782 19.0168 14.6713 19.062 14.6555 19.1043C14.6398 19.1467 14.6156 19.1855 14.5844 19.2182C14.5532 19.251 14.5157 19.277 14.4741 19.2948C14.4326 19.3126 14.3878 19.3217 14.3426 19.3217H10.6655C10.515 19.3219 10.3688 19.2712 10.2508 19.1779C10.1328 19.0845 10.0498 18.954 10.0154 18.8075C9.99394 18.7072 9.99493 18.6034 10.0183 18.5036C10.0416 18.4037 10.0867 18.3103 10.1504 18.2299C10.7386 17.4498 11.5191 16.8355 12.4157 16.4472C12.0221 16.0883 11.7202 15.6403 11.5353 15.1408C11.3504 14.6412 11.2879 14.1047 11.3531 13.576C11.4182 13.0474 11.609 12.542 11.9096 12.1023C12.2102 11.6625 12.6118 11.3012 13.0808 11.0486C13.5497 10.796 14.0724 10.6595 14.605 10.6504C15.1375 10.6413 15.6645 10.76 16.1418 10.9964C16.6191 11.2329 17.0328 11.5803 17.3482 12.0095C17.6636 12.4388 17.8716 12.9373 17.9547 13.4635C17.9654 13.5342 17.9528 13.6065 17.9186 13.6694C17.8845 13.7323 17.8307 13.7823 17.7655 13.8118C16.8407 14.2394 16.0575 14.9225 15.5083 15.7806C14.9591 16.6388 14.6668 17.6361 14.666 18.6549C14.666 18.7616 14.666 18.8666 14.676 18.9716ZM29.8445 18.229C29.2576 17.4498 28.4789 16.8359 27.5842 16.4472C27.9778 16.0883 28.2797 15.6403 28.4646 15.1408C28.6495 14.6412 28.712 14.1047 28.6469 13.576C28.5817 13.0474 28.3909 12.542 28.0903 12.1023C27.7897 11.6625 27.3881 11.3012 26.9191 11.0486C26.4502 10.796 25.9275 10.6595 25.395 10.6504C24.8624 10.6413 24.3354 10.76 23.8581 10.9964C23.3808 11.2329 22.9671 11.5803 22.6517 12.0095C22.3363 12.4388 22.1283 12.9373 22.0452 13.4635C22.0345 13.5342 22.0472 13.6065 22.0813 13.6694C22.1155 13.7323 22.1692 13.7823 22.2344 13.8118C23.1592 14.2394 23.9424 14.9225 24.4916 15.7806C25.0408 16.6388 25.3331 17.6361 25.334 18.6549C25.334 18.7616 25.334 18.8666 25.324 18.9716C25.3217 19.0168 25.3286 19.062 25.3444 19.1043C25.3601 19.1467 25.3843 19.1855 25.4155 19.2182C25.4467 19.251 25.4842 19.277 25.5258 19.2948C25.5674 19.3126 25.6121 19.3217 25.6573 19.3217H29.3345C29.4849 19.3219 29.6311 19.2712 29.7491 19.1779C29.8671 19.0845 29.9501 18.954 29.9845 18.8075C30.0061 18.707 30.0051 18.603 29.9816 18.503C29.9581 18.403 29.9127 18.3094 29.8487 18.229H29.8445ZM22.4269 21.8278C23.0908 21.3194 23.5787 20.6157 23.822 19.8157C24.0653 19.0157 24.0517 18.1595 23.7833 17.3676C23.5149 16.5757 23.0051 15.8877 22.3255 15.4005C21.6459 14.9133 20.8307 14.6513 19.9945 14.6513C19.1583 14.6513 18.3432 14.9133 17.6636 15.4005C16.984 15.8877 16.4742 16.5757 16.2057 17.3676C15.9373 18.1595 15.9238 19.0157 16.1671 19.8157C16.4104 20.6157 16.8983 21.3194 17.5622 21.8278C16.3841 22.3383 15.4004 23.2124 14.7551 24.3223C14.6966 24.4237 14.6658 24.5387 14.6658 24.6557C14.6658 24.7728 14.6966 24.8878 14.7552 24.9891C14.8137 25.0905 14.8979 25.1747 14.9993 25.2332C15.1007 25.2917 15.2157 25.3225 15.3327 25.3224H24.6672C24.7843 25.3225 24.8993 25.2917 25.0006 25.2332C25.102 25.1747 25.1862 25.0905 25.2447 24.9891C25.3033 24.8878 25.3341 24.7728 25.3341 24.6557C25.3341 24.5387 25.3033 24.4237 25.2448 24.3223C24.5981 23.2117 23.6126 22.3375 22.4328 21.8278H22.4269Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_4441_41328" x="0" y="0.649902" width="40" height="34.6724" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4441_41328"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4441_41328" result="shape"/>
</filter>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -81,6 +81,10 @@ QString ConferenceInfoModel::getSubject() const {
return Utils::coreStringToAppString(mConferenceInfo->getSubject()); return Utils::coreStringToAppString(mConferenceInfo->getSubject());
} }
linphone::ConferenceInfo::State ConferenceInfoModel::getState() const {
return mConferenceInfo->getState();
}
QString ConferenceInfoModel::getOrganizerName() const { QString ConferenceInfoModel::getOrganizerName() const {
auto organizer = mConferenceInfo->getOrganizer(); auto organizer = mConferenceInfo->getOrganizer();
auto name = Utils::coreStringToAppString(organizer->getDisplayName()); auto name = Utils::coreStringToAppString(organizer->getDisplayName());
@ -142,4 +146,9 @@ void ConferenceInfoModel::deleteConferenceInfo() {
void ConferenceInfoModel::cancelConference() { void ConferenceInfoModel::cancelConference() {
if (!mConferenceSchedulerModel) return; if (!mConferenceSchedulerModel) return;
mConferenceSchedulerModel->cancelConference(mConferenceInfo); mConferenceSchedulerModel->cancelConference(mConferenceInfo);
emit conferenceInfoCanceled();
}
void ConferenceInfoModel::updateConferenceInfo() {
mConferenceSchedulerModel->setInfo(mConferenceInfo);
} }

View file

@ -42,6 +42,7 @@ public:
int getDuration() const; int getDuration() const;
QDateTime getEndTime() const; QDateTime getEndTime() const;
QString getSubject() const; QString getSubject() const;
linphone::ConferenceInfo::State getState() const;
QString getOrganizerName() const; QString getOrganizerName() const;
QString getOrganizerAddress() const; QString getOrganizerAddress() const;
QString getDescription() const; QString getDescription() const;
@ -55,6 +56,7 @@ public:
void setParticipantInfos(const std::list<std::shared_ptr<linphone::ParticipantInfo>> &participantInfos); void setParticipantInfos(const std::list<std::shared_ptr<linphone::ParticipantInfo>> &participantInfos);
void deleteConferenceInfo(); void deleteConferenceInfo();
void cancelConference(); void cancelConference();
void updateConferenceInfo();
signals: signals:
void dateTimeChanged(const QDateTime &date); void dateTimeChanged(const QDateTime &date);
@ -64,6 +66,7 @@ signals:
void descriptionChanged(const QString &description); void descriptionChanged(const QString &description);
void participantsChanged(); void participantsChanged();
void conferenceInfoDeleted(); void conferenceInfoDeleted();
void conferenceInfoCanceled();
void schedulerStateChanged(linphone::ConferenceScheduler::State state); void schedulerStateChanged(linphone::ConferenceScheduler::State state);
void infoStateChanged(linphone::ConferenceInfo::State state); void infoStateChanged(linphone::ConferenceInfo::State state);
void invitationsSent(const std::list<std::shared_ptr<linphone::Address>> &failedInvitations); void invitationsSent(const std::list<std::shared_ptr<linphone::Address>> &failedInvitations);

View file

@ -57,6 +57,6 @@ void SettingsModel::setVideoDevice(const std::string &id) {
auto core = CoreModel::getInstance()->getCore(); auto core = CoreModel::getInstance()->getCore();
if (core->getVideoDevice() != id) { if (core->getVideoDevice() != id) {
CoreModel::getInstance()->getCore()->setVideoDevice(id); CoreModel::getInstance()->getCore()->setVideoDevice(id);
emit videoDeviceChanged(); emit videoDeviceChanged(id);
} }
} }

View file

@ -49,7 +49,7 @@ public:
std::shared_ptr<linphone::Config> mConfig; std::shared_ptr<linphone::Config> mConfig;
signals: signals:
void videoDeviceChanged(); void videoDeviceChanged(const std::string &id);
private: private:
DECLARE_ABSTRACT_OBJECT DECLARE_ABSTRACT_OBJECT

View file

@ -22,6 +22,8 @@
#include "core/App.hpp" #include "core/App.hpp"
#include "core/call/CallGui.hpp" #include "core/call/CallGui.hpp"
#include "core/conference/ConferenceInfoCore.hpp"
#include "core/conference/ConferenceInfoGui.hpp"
#include "core/path/Paths.hpp" #include "core/path/Paths.hpp"
#include "model/object/VariantObject.hpp" #include "model/object/VariantObject.hpp"
#include "model/tool/ToolModel.hpp" #include "model/tool/ToolModel.hpp"
@ -120,10 +122,26 @@ VariantObject *Utils::createCall(const QString &sipAddress,
return data; return data;
} }
void Utils::setupConference(ConferenceInfoGui *confGui) {
if (!confGui) return;
auto window = App::getInstance()->getCallsWindow(QVariant());
window->setProperty("conferenceInfo", QVariant::fromValue(confGui));
window->show();
}
void Utils::openCallsWindow(CallGui *call) { void Utils::openCallsWindow(CallGui *call) {
if (call) App::getInstance()->getCallsWindow(QVariant::fromValue(call))->show(); if (call) App::getInstance()->getCallsWindow(QVariant::fromValue(call))->show();
} }
void Utils::setCallsWindowCall(CallGui *call) {
if (call) App::getInstance()->setCallsWindowProperty("call", QVariant::fromValue(call));
}
void Utils::setCallsWindowProperty(const QString &id, const QVariant &property) {
const char *idChar = id.toLocal8Bit().data();
App::getInstance()->setCallsWindowProperty(idChar, property);
}
QQuickWindow *Utils::getCallsWindow(CallGui *callGui) { QQuickWindow *Utils::getCallsWindow(CallGui *callGui) {
auto app = App::getInstance(); auto app = App::getInstance();
auto window = app->getCallsWindow(QVariant::fromValue(callGui)); auto window = app->getCallsWindow(QVariant::fromValue(callGui));
@ -141,9 +159,12 @@ QQuickWindow *Utils::getMainWindow() {
return win; return win;
} }
void Utils::showInformationPopup(const QString &title, const QString &description, bool isSuccess) { void Utils::showInformationPopup(const QString &title,
auto win = App::getInstance()->getMainWindow(); const QString &description,
QMetaObject::invokeMethod(win, "showInformationPopup", Q_ARG(QVariant, title), Q_ARG(QVariant, description), bool isSuccess,
QQuickWindow *window) {
if (!window) window = App::getInstance()->getMainWindow();
QMetaObject::invokeMethod(window, "showInformationPopup", Q_ARG(QVariant, title), Q_ARG(QVariant, description),
Q_ARG(QVariant, isSuccess)); Q_ARG(QVariant, isSuccess));
} }
@ -1173,16 +1194,20 @@ int Utils::getYear(const QDate &date) {
} }
bool Utils::isMe(const QString &address) { bool Utils::isMe(const QString &address) {
auto linAddr = ToolModel::interpretUrl(address); bool isMe = false;
if (!CoreModel::getInstance()->getCore()->getDefaultAccount()) { App::postModelSync([&isMe, address]() {
for (auto &account : CoreModel::getInstance()->getCore()->getAccountList()) { auto linAddr = ToolModel::interpretUrl(address);
if (account->getContactAddress()->weakEqual(linAddr)) return true; if (!CoreModel::getInstance()->getCore()->getDefaultAccount()) {
// for (auto &account : CoreModel::getInstance()->getCore()->getAccountList()) {
// if (account->getContactAddress()->weakEqual(linAddr)) return true;
// }
isMe = false;
} else {
auto accountAddr = CoreModel::getInstance()->getCore()->getDefaultAccount()->getContactAddress();
isMe = linAddr && accountAddr ? accountAddr->weakEqual(linAddr) : false;
} }
return false; });
} else { return isMe;
auto accountAddr = CoreModel::getInstance()->getCore()->getDefaultAccount()->getContactAddress();
return linAddr && accountAddr ? accountAddr->weakEqual(linAddr) : false;
}
} }
// QDateTime dateTime(QDateTime::fromString(date, "yyyy-MM-dd hh:mm:ss")); // QDateTime dateTime(QDateTime::fromString(date, "yyyy-MM-dd hh:mm:ss"));

View file

@ -44,6 +44,7 @@ class CallGui;
class QQuickWindow; class QQuickWindow;
class VariantObject; class VariantObject;
class CallGui; class CallGui;
class ConferenceInfoGui;
class Utils : public QObject { class Utils : public QObject {
Q_OBJECT Q_OBJECT
@ -61,9 +62,14 @@ public:
const QString &prepareTransfertAddress = "", const QString &prepareTransfertAddress = "",
const 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 setCallsWindowCall(CallGui *call);
Q_INVOKABLE static void setCallsWindowProperty(const QString &id, const QVariant &property);
Q_INVOKABLE static QQuickWindow *getMainWindow(); Q_INVOKABLE static QQuickWindow *getMainWindow();
Q_INVOKABLE static void Q_INVOKABLE static void showInformationPopup(const QString &title,
showInformationPopup(const QString &title, const QString &description, bool isSuccess = true); const QString &description,
bool isSuccess = true,
QQuickWindow *window = nullptr);
Q_INVOKABLE static QQuickWindow *getCallsWindow(CallGui *callGui); Q_INVOKABLE static QQuickWindow *getCallsWindow(CallGui *callGui);
Q_INVOKABLE static void closeCallsWindow(); Q_INVOKABLE static void closeCallsWindow();
Q_INVOKABLE static VariantObject *haveAccount(); Q_INVOKABLE static VariantObject *haveAccount();

View file

@ -15,11 +15,30 @@ Window {
// modality: Qt.WindowModal // modality: Qt.WindowModal
property CallGui call property CallGui call
property ConferenceInfoGui conferenceInfo
onConferenceInfoChanged: console.log("CONFERENCE INFO", conferenceInfo)
property ConferenceGui conference: call && call.core.conference || null property ConferenceGui conference: call && call.core.conference || null
property bool callTerminatedByUser: false property bool callTerminatedByUser: false
onCallChanged: {
console.log("CALL", call)
// if conference, the main item is only
// displayed when state is connected
if (call && !conferenceInfo) middleItemStackView.replace(inCallItem)
}
Component.onCompleted: if (call && !conferenceInfo) middleItemStackView.replace(inCallItem)
function joinConference(withVideo) {
if (!conferenceInfo || conferenceInfo.core.uri.length === 0) UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("La conférence n'a pas pu démarrer en raison d'une erreur d'uri."))
else {
var callObj = UtilsCpp.createCall(conferenceInfo.core.uri, withVideo)
}
}
Connections { Connections {
target: call.core enabled: call != undefined && call != null
target: call && call.core
onRemoteVideoEnabledChanged: console.log("remote video enabled", call.core.remoteVideoEnabled) onRemoteVideoEnabledChanged: console.log("remote video enabled", call.core.remoteVideoEnabled)
onSecurityUpdated: { onSecurityUpdated: {
if (call.core.isSecured) { if (call.core.isSecured) {
@ -32,16 +51,11 @@ Window {
} }
} }
onCallChanged: { property var callState: call && call.core.state
waitingTime.seconds = 0
waitingTimer.restart()
console.log("call changed", call, waitingTime.seconds)
}
property var callState: call.core.state
onCallStateChanged: { onCallStateChanged: {
console.log("State:", callState) console.log("State:", callState)
if (callState === LinphoneEnums.CallState.Connected) { if (callState === LinphoneEnums.CallState.Connected) {
if (conferenceInfo) middleItemStackView.replace(inCallItem)
if(!call.core.isSecured && call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp) { if(!call.core.isSecured && call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp) {
zrtpValidation.open() zrtpValidation.open()
} }
@ -50,23 +64,24 @@ Window {
callEnded(call) callEnded(call)
} }
} }
property var transferState: call.core.transferState property var transferState: call && call.core.transferState
onTransferStateChanged: { onTransferStateChanged: {
console.log("Transfer state:", transferState) console.log("Transfer state:", transferState)
if (call.core.transferState === LinphoneEnums.CallState.Error) { if (transferState === LinphoneEnums.CallState.Error) {
transferErrorPopup.visible = true transferErrorPopup.visible = true
} }
else if (call.core.transferState === LinphoneEnums.CallState.Connected){ else if (transferState === LinphoneEnums.CallState.Connected){
var mainWin = UtilsCpp.getMainWindow() var mainWin = UtilsCpp.getMainWindow()
UtilsCpp.smartShowWindow(mainWin) UtilsCpp.smartShowWindow(mainWin)
mainWin.transferCallSucceed() mainWin.transferCallSucceed()
} }
} }
onClosing: (close) => { onClosing: (close) => {
close.accepted = false if (callsModel.haveCall) {
if (callsModel.haveCall) close.accepted = false
terminateAllCallsDialog.open() terminateAllCallsDialog.open()
}
} }
Timer { Timer {
@ -144,9 +159,9 @@ Window {
} }
Popup { Popup {
id: waitingPopup id: waitingPopup
visible: mainWindow.call.core.transferState === LinphoneEnums.CallState.OutgoingInit visible: mainWindow.transferState === LinphoneEnums.CallState.OutgoingInit
|| mainWindow.call.core.transferState === LinphoneEnums.CallState.OutgoingProgress || mainWindow.transferState === LinphoneEnums.CallState.OutgoingProgress
|| mainWindow.call.core.transferState === LinphoneEnums.CallState.OutgoingRinging || false || mainWindow.transferState === LinphoneEnums.CallState.OutgoingRinging || false
modal: true modal: true
closePolicy: Control.Popup.NoAutoClose closePolicy: Control.Popup.NoAutoClose
anchors.centerIn: parent anchors.centerIn: parent
@ -211,31 +226,43 @@ Window {
spacing: 10 * DefaultStyle.dp spacing: 10 * DefaultStyle.dp
EffectImage { EffectImage {
id: callStatusIcon id: callStatusIcon
width: 15 * DefaultStyle.dp Layout.preferredWidth: 30 * DefaultStyle.dp
height: 15 * DefaultStyle.dp Layout.preferredHeight: 30 * DefaultStyle.dp
imageSource:(mainWindow.call.core.state === LinphoneEnums.CallState.End // TODO : change with broadcast or meeting icon when available
|| mainWindow.call.core.state === LinphoneEnums.CallState.Released) // +
? AppIcons.endCall imageSource: !mainWindow.call
: (mainWindow.call.core.state === LinphoneEnums.CallState.Paused ? AppIcons.meeting
|| mainWindow.call.core.state === LinphoneEnums.CallState.PausedByRemote) : (mainWindow.callState === LinphoneEnums.CallState.End
? AppIcons.pause || mainWindow.callState === LinphoneEnums.CallState.Released)
: mainWindow.call.core.dir === LinphoneEnums.CallDir.Outgoing ? AppIcons.endCall
? AppIcons.outgoingCall : (mainWindow.callState === LinphoneEnums.CallState.Paused
: AppIcons.incomingCall || mainWindow.callState === LinphoneEnums.CallState.PausedByRemote)
colorizationColor: mainWindow.call.core.state === LinphoneEnums.CallState.Paused ? AppIcons.pause
|| mainWindow.call.core.state === LinphoneEnums.CallState.PausedByRemote || mainWindow.call.core.state === LinphoneEnums.CallState.End : mainWindow.conferenceInfo
|| mainWindow.call.core.state === LinphoneEnums.CallState.Released ? DefaultStyle.danger_500main : undefined ? AppIcons.usersThree
: mainWindow.call.core.dir === LinphoneEnums.CallDir.Outgoing
? AppIcons.arrowUpRight
: AppIcons.arrowDownLeft
colorizationColor: !mainWindow.call || mainWindow.callState === LinphoneEnums.CallState.Paused
|| mainWindow.callState === LinphoneEnums.CallState.PausedByRemote || mainWindow.callState === LinphoneEnums.CallState.End
|| mainWindow.callState === LinphoneEnums.CallState.Released || mainWindow.conferenceInfo
? DefaultStyle.danger_500main
: mainWindow.call.core.dir === LinphoneEnums.CallDir.Outgoing
? DefaultStyle.info_500_main
: DefaultStyle.success_500main
} }
Text { Text {
id: callStatusText id: callStatusText
text: (mainWindow.call.core.state === LinphoneEnums.CallState.End || mainWindow.call.core.state === LinphoneEnums.CallState.Released) text: (mainWindow.callState === LinphoneEnums.CallState.End || mainWindow.callState === LinphoneEnums.CallState.Released)
? qsTr("End of the call") ? qsTr("End of the call")
: (mainWindow.call.core.state === LinphoneEnums.CallState.Paused : (mainWindow.callState === LinphoneEnums.CallState.Paused
|| mainWindow.call.core.state === LinphoneEnums.CallState.PausedByRemote) || mainWindow.callState === LinphoneEnums.CallState.PausedByRemote)
? qsTr("Appel mis en pause") ? qsTr("Appel mis en pause")
: mainWindow.conference : mainWindow.conferenceInfo
? mainWindow.conference.core.subject ? mainWindow.conferenceInfo.core.subject
: EnumsToStringCpp.dirToString(mainWindow.call.core.dir) + qsTr(" call") : mainWindow.call
? EnumsToStringCpp.dirToString(mainWindow.call.core.dir) + qsTr(" call")
: ""
color: DefaultStyle.grey_0 color: DefaultStyle.grey_0
font { font {
pixelSize: 22 * DefaultStyle.dp pixelSize: 22 * DefaultStyle.dp
@ -243,30 +270,42 @@ Window {
} }
} }
Rectangle { Rectangle {
visible: mainWindow.call.core.state === LinphoneEnums.CallState.Connected visible: mainWindow.call && (mainWindow.callState === LinphoneEnums.CallState.Connected
|| mainWindow.call.core.state === LinphoneEnums.CallState.StreamsRunning || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning)
Layout.preferredHeight: parent.height Layout.preferredHeight: parent.height
Layout.preferredWidth: 2 * DefaultStyle.dp Layout.preferredWidth: 2 * DefaultStyle.dp
} }
Text { Text {
text: UtilsCpp.formatElapsedTime(mainWindow.call.core.duration) text: mainWindow.call ? UtilsCpp.formatElapsedTime(mainWindow.call.core.duration) : ""
color: DefaultStyle.grey_0 color: DefaultStyle.grey_0
font { font {
pixelSize: 22 * DefaultStyle.dp pixelSize: 22 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp weight: 800 * DefaultStyle.dp
} }
visible: mainWindow.call.core.state === LinphoneEnums.CallState.Connected visible: mainWindow.callState === LinphoneEnums.CallState.Connected
|| mainWindow.call.core.state === LinphoneEnums.CallState.StreamsRunning || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning
}
Text {
text: mainWindow.conferenceInfo ? mainWindow.conferenceInfo.core.getStartEndDateString() : ""
color: DefaultStyle.grey_0
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
} }
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
} }
RowLayout { RowLayout {
visible: mainWindow.call.core.recording || mainWindow.call.core.remoteRecording visible: mainWindow.call && (mainWindow.call.core.recording || mainWindow.call.core.remoteRecording)
Text { Text {
color: DefaultStyle.danger_500main color: DefaultStyle.danger_500main
font.pixelSize: 14 * DefaultStyle.dp font.pixelSize: 14 * DefaultStyle.dp
text: mainWindow.call.core.recording ? qsTr("Vous enregistrez l'appel") : qsTr("Votre correspondant enregistre l'appel") text: mainWindow.call
? mainWindow.call.core.recording
? qsTr("Vous enregistrez l'appel")
: qsTr("Votre correspondant enregistre l'appel")
: ""
} }
EffectImage { EffectImage {
imageSource: AppIcons.recordFill imageSource: AppIcons.recordFill
@ -278,13 +317,13 @@ Window {
} }
Control.Control { Control.Control {
visible: mainWindow.call && mainWindow.call.core.isSecured
anchors.centerIn: parent anchors.centerIn: parent
topPadding: 8 * DefaultStyle.dp topPadding: 8 * DefaultStyle.dp
bottomPadding: 8 * DefaultStyle.dp bottomPadding: 8 * DefaultStyle.dp
leftPadding: 10 * DefaultStyle.dp leftPadding: 10 * DefaultStyle.dp
rightPadding: 10 * DefaultStyle.dp rightPadding: 10 * DefaultStyle.dp
width: 269 * DefaultStyle.dp width: 269 * DefaultStyle.dp
visible: mainWindow.call && mainWindow.call.core.isSecured
background: Rectangle { background: Rectangle {
anchors.fill: parent anchors.fill: parent
border.color: DefaultStyle.info_500_main border.color: DefaultStyle.info_500_main
@ -311,162 +350,14 @@ Window {
} }
} }
RowLayout { RowLayout {
Control.Control { Layout.fillWidth: true
Layout.fillHeight: true
Control.StackView {
id: middleItemStackView
initialItem: waitingRoom
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredWidth: 1059 * DefaultStyle.dp
Layout.fillHeight: true Layout.fillHeight: true
Layout.leftMargin: 10 * DefaultStyle.dp Layout.margins: 20 * DefaultStyle.dp
Layout.rightMargin: 10 * DefaultStyle.dp
Layout.alignment: Qt.AlignCenter
background: Rectangle {
anchors.fill: parent
color: DefaultStyle.grey_600
radius: 15 * DefaultStyle.dp
}
contentItem: Item {
id: centerItem
anchors.fill: parent
Text {
id: callTerminatedText
Connections {
target: mainWindow
onCallStateChanged: {
if (mainWindow.call.core.state === LinphoneEnums.CallState.End) {
callTerminatedText.visible = true
}
}
}
visible: false
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 25 * DefaultStyle.dp
text: mainWindow.callTerminatedByUser ? qsTr("Vous avez terminé l'appel") : qsTr("Votre correspondant a terminé l'appel")
color: DefaultStyle.grey_0
z: 1
font {
pixelSize: 22 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
}
StackLayout {
id: centerLayout
currentIndex: 0
anchors.fill: parent
Connections {
target: mainWindow
onCallStateChanged: {
if (mainWindow.call.core.state === LinphoneEnums.CallState.Error) {
centerLayout.currentIndex = 1
}
}
}
Sticker {
call: mainWindow.call
Layout.fillWidth: true
Layout.fillHeight: true
// visible: mainWindow.call.core.state != LinphoneEnums.CallState.End
Timer {
id: waitingTimer
interval: 1000
repeat: true
onTriggered: waitingTime.seconds += 1
}
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 30 * DefaultStyle.dp
visible: mainWindow.call.core.state == LinphoneEnums.CallState.OutgoingInit
|| mainWindow.call.core.state == LinphoneEnums.CallState.OutgoingProgress
|| mainWindow.call.core.state == LinphoneEnums.CallState.OutgoingRinging
|| mainWindow.call.core.state == LinphoneEnums.CallState.OutgoingEarlyMedia
|| mainWindow.call.core.state == LinphoneEnums.CallState.IncomingReceived
BusyIndicator {
indicatorColor: DefaultStyle.main2_100
Layout.alignment: Qt.AlignHCenter
}
Text {
id: waitingTime
property int seconds
text: UtilsCpp.formatElapsedTime(seconds)
color: DefaultStyle.grey_0
Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
font {
pixelSize: 30 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
Component.onCompleted: {
waitingTimer.restart()
}
}
}
}
ColumnLayout {
id: userNotFoundLayout
Layout.preferredWidth: parent.width
Layout.preferredHeight: parent.height
Layout.alignment: Qt.AlignCenter
Text {
text: qsTr(mainWindow.call.core.lastErrorMessage)
Layout.alignment: Qt.AlignCenter
color: DefaultStyle.grey_0
font.pixelSize: 40 * DefaultStyle.dp
}
}
}
Sticker {
id: preview
visible: mainWindow.call.core.state != LinphoneEnums.CallState.End
&& mainWindow.call.core.state != LinphoneEnums.CallState.Released
height: 180 * DefaultStyle.dp
width: 300 * DefaultStyle.dp
anchors.right: centerItem.right
anchors.bottom: centerItem.bottom
anchors.rightMargin: 10 * DefaultStyle.dp
anchors.bottomMargin: 10 * DefaultStyle.dp
AccountProxy{
id: accounts
}
account: accounts.defaultAccount
enablePersonalCamera: mainWindow.call.core.cameraEnabled
MovableMouseArea {
id: previewMouseArea
anchors.fill: parent
// visible: mainItem.participantCount <= 2
movableArea: centerItem
margin: 10 * DefaultStyle.dp
function resetPosition(){
preview.anchors.right = centerItem.right
preview.anchors.bottom = centerItem.bottom
preview.anchors.rightMargin = previewMouseArea.margin
preview.anchors.bottomMargin = previewMouseArea.margin
}
onVisibleChanged: if(!visible){
resetPosition()
}
drag.target: preview
onDraggingChanged: if(dragging) {
preview.anchors.right = undefined
preview.anchors.bottom = undefined
}
onRequestResetPosition: resetPosition()
}
}
property int previousWidth
Component.onCompleted: {
previousWidth = width
}
onWidthChanged: {
if (width < previousWidth) {
previewMouseArea.updatePosition(0, 0)
} else {
previewMouseArea.updatePosition(width - previousWidth, 0)
}
previousWidth = width
}
}
} }
OngoingCallRightPanel { OngoingCallRightPanel {
id: rightPanel id: rightPanel
@ -497,6 +388,7 @@ Window {
Component { Component {
id: contactsListPanel id: contactsListPanel
CallContactsLists { CallContactsLists {
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Transfert d'appel")
sideMargin: 10 * DefaultStyle.dp sideMargin: 10 * DefaultStyle.dp
topMargin: 15 * DefaultStyle.dp topMargin: 15 * DefaultStyle.dp
groupCallVisible: false groupCallVisible: false
@ -505,7 +397,6 @@ Window {
onCallButtonPressed: (address) => { onCallButtonPressed: (address) => {
mainWindow.call.core.lTransferCall(address) mainWindow.call.core.lTransferCall(address)
} }
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Transfert d'appel")
} }
} }
Component { Component {
@ -548,12 +439,11 @@ Window {
Component { Component {
id: callsListPanel id: callsListPanel
ColumnLayout { ColumnLayout {
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Liste d'appel")
RoundedBackgroundControl { RoundedBackgroundControl {
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Liste d'appel")
Layout.fillWidth: true Layout.fillWidth: true
// height: Math.min(callList.height + topPadding + bottomPadding, rightPanelStack.height) // height: Math.min(callList.height + topPadding + bottomPadding, rightPanelStack.height)
onHeightChanged: console.log("calls list height changed", height) Layout.preferredHeight: Math.min(callList.height + topPadding + bottomPadding, rightPanelStack.height)
height: Math.min(callList.height + topPadding + bottomPadding, rightPanelStack.height)
topPadding: 15 * DefaultStyle.dp topPadding: 15 * DefaultStyle.dp
bottomPadding: 15 * DefaultStyle.dp bottomPadding: 15 * DefaultStyle.dp
@ -680,152 +570,206 @@ Window {
} }
Component { Component {
id: settingsPanel id: settingsPanel
ColumnLayout { InCallSettingsPanel {
RoundedBackgroundControl { Control.StackView.onActivated: rightPanelTitle.text = qsTr("Paramètres")
Layout.alignment: Qt.AlignHCenter call: mainWindow.call
Control.StackView.onActivated: { }
rightPanelTitle.text = qsTr("Paramètres") }
}
}
}
Component {
id: waitingRoom
WaitingRoom {
id: waitingRoomIn
Layout.alignment: Qt.AlignCenter
conferenceInfo: mainWindow.conferenceInfo
onSettingsButtonCheckedChanged: {
if (settingsButtonChecked) {
rightPanel.visible = true
rightPanel.replace(settingsPanel)
} else {
rightPanel.visible = false
}
}
Connections {
target: rightPanel
onVisibleChanged: if (!visible) waitingRoomIn.settingsButtonChecked = false
}
Connections {
target: mainWindow
onCallChanged: if (mainWindow.conferenceInfo && mainWindow.call) {
mainWindow.call.core.lSetCameraEnabled(waitingRoomIn.cameraEnabled)
mainWindow.call.core.lSetMicrophoneMuted(!waitingRoomIn.microEnabled)
}
}
onJoinConfRequested: mainWindow.joinConference(cameraEnabled)
}
}
Component {
id: inCallItem
Control.Control {
Layout.fillWidth: true
implicitWidth: 1059 * DefaultStyle.dp
// implicitHeight: parent.height
Layout.fillHeight: true
Layout.leftMargin: 10 * DefaultStyle.dp
Layout.rightMargin: 10 * DefaultStyle.dp
Layout.alignment: Qt.AlignCenter
background: Rectangle {
anchors.fill: parent
color: DefaultStyle.grey_600
radius: 15 * DefaultStyle.dp
}
contentItem: Item {
id: centerItem
anchors.fill: parent
Text {
id: callTerminatedText
Connections {
target: mainWindow
onCallStateChanged: {
if (mainWindow.callState === LinphoneEnums.CallState.End) {
callTerminatedText.visible = true
} }
backgroundColor: DefaultStyle.main2_0
height: contentItem.implicitHeight + topPadding + bottomPadding
Layout.fillWidth: true
topPadding: 25 * DefaultStyle.dp
bottomPadding: 25 * DefaultStyle.dp
leftPadding: 25 * DefaultStyle.dp
rightPadding: 25 * DefaultStyle.dp
contentItem: ColumnLayout {
spacing: 10 * DefaultStyle.dp
RowLayout {
Layout.fillWidth: true
EffectImage {
imageSource: AppIcons.speaker
colorizationColor: DefaultStyle.main1_500_main
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
imageWidth: 24 * DefaultStyle.dp
imageHeight: 24 * DefaultStyle.dp
}
Text {
text: qsTr("Haut-parleurs")
Layout.fillWidth: true
}
}
ComboBox {
Layout.fillWidth: true
Layout.preferredWidth: parent.width
model: SettingsCpp.outputAudioDevicesList
onCurrentTextChanged: {
mainWindow.call.core.lSetOutputAudioDevice(currentText)
}
}
Slider {
id: speakerVolume
Layout.fillWidth: true
from: 0.0
to: 1.0
value: mainWindow.call && mainWindow.call.core.speakerVolumeGain
onMoved: {
mainWindow.call.core.lSetSpeakerVolumeGain(value)
}
}
RowLayout {
Layout.fillWidth: true
EffectImage {
imageSource: AppIcons.microphone
colorizationColor: DefaultStyle.main1_500_main
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
imageWidth: 24 * DefaultStyle.dp
imageHeight: 24 * DefaultStyle.dp
}
Text {
text: qsTr("Microphone")
Layout.fillWidth: true
}
}
ComboBox {
Layout.fillWidth: true
Layout.preferredWidth: parent.width
model: SettingsCpp.inputAudioDevicesList
onCurrentTextChanged: {
mainWindow.call.core.lSetInputAudioDevice(currentText)
}
}
Slider {
id: microVolume
Layout.fillWidth: true
from: 0.0
to: 1.0
value: mainWindow.call && mainWindow.call.core.microphoneVolumeGain
onMoved: {
mainWindow.call.core.lSetMicrophoneVolumeGain(value)
}
}
Timer {
interval: 50
repeat: true
running: mainWindow.call || false
onTriggered: audioTestSlider.value = (mainWindow.call && mainWindow.call.core.microVolume)
}
Slider {
id: audioTestSlider
Layout.fillWidth: true
enabled: false
Layout.preferredHeight: 10 * DefaultStyle.dp
background: Rectangle {
x: audioTestSlider.leftPadding
y: audioTestSlider.topPadding + audioTestSlider.availableHeight / 2 - height / 2
implicitWidth: 200 * DefaultStyle.dp
implicitHeight: 10 * DefaultStyle.dp
width: audioTestSlider.availableWidth
height: implicitHeight
radius: 2 * DefaultStyle.dp
color: "#D9D9D9"
Rectangle {
width: audioTestSlider.visualPosition * parent.width
height: parent.height
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: "#6FF88D" }
GradientStop { position: 1.0; color: "#00D916" }
}
radius: 2 * DefaultStyle.dp
}
}
handle: Item {visible: false}
}
RowLayout {
Layout.fillWidth: true
EffectImage {
imageSource: AppIcons.videoCamera
colorizationColor: DefaultStyle.main1_500_main
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
imageWidth: 24 * DefaultStyle.dp
imageHeight: 24 * DefaultStyle.dp
}
Text {
text: qsTr("Caméra")
Layout.fillWidth: true
}
}
ComboBox {
Layout.fillWidth: true
Layout.preferredWidth: parent.width
model: SettingsCpp.videoDevicesList
onCurrentTextChanged: {
SettingsCpp.lSetVideoDevice(currentText)
}
}
}
}
Item {
Layout.fillHeight: true
} }
} }
visible: false
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 25 * DefaultStyle.dp
text: mainWindow.callTerminatedByUser ? qsTr("Vous avez terminé l'appel") : qsTr("Votre correspondant a terminé l'appel")
color: DefaultStyle.grey_0
z: 1
font {
pixelSize: 22 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
}
StackLayout {
id: centerLayout
currentIndex: 0
anchors.fill: parent
Connections {
target: mainWindow
onCallStateChanged: {
if (mainWindow.callState === LinphoneEnums.CallState.Error) {
centerLayout.currentIndex = 1
}
}
}
Sticker {
call: mainWindow.call
Layout.fillWidth: true
Layout.fillHeight: true
// visible: mainWindow.callState != LinphoneEnums.CallState.End
Connections {
target: mainWindow
onCallChanged: {
waitingTime.seconds = 0
waitingTimer.restart()
console.log("call changed", call, waitingTime.seconds)
}
}
Timer {
id: waitingTimer
interval: 1000
repeat: true
onTriggered: waitingTime.seconds += 1
}
ColumnLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 30 * DefaultStyle.dp
visible: mainWindow.callState == LinphoneEnums.CallState.OutgoingInit
|| mainWindow.callState == LinphoneEnums.CallState.OutgoingProgress
|| mainWindow.callState == LinphoneEnums.CallState.OutgoingRinging
|| mainWindow.callState == LinphoneEnums.CallState.OutgoingEarlyMedia
|| mainWindow.callState == LinphoneEnums.CallState.IncomingReceived
BusyIndicator {
indicatorColor: DefaultStyle.main2_100
Layout.alignment: Qt.AlignHCenter
}
Text {
id: waitingTime
property int seconds
text: UtilsCpp.formatElapsedTime(seconds)
color: DefaultStyle.grey_0
Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
font {
pixelSize: 30 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
Component.onCompleted: {
waitingTimer.restart()
}
}
}
}
ColumnLayout {
id: errorLayout
Layout.preferredWidth: parent.width
Layout.preferredHeight: parent.height
Layout.alignment: Qt.AlignCenter
Text {
text: qsTr(mainWindow.call.core.lastErrorMessage)
Layout.alignment: Qt.AlignCenter
color: DefaultStyle.grey_0
font.pixelSize: 40 * DefaultStyle.dp
}
}
}
Sticker {
id: preview
visible: mainWindow.callState != LinphoneEnums.CallState.End
&& mainWindow.callState != LinphoneEnums.CallState.Released
height: 180 * DefaultStyle.dp
width: 300 * DefaultStyle.dp
anchors.right: centerItem.right
anchors.bottom: centerItem.bottom
anchors.rightMargin: 10 * DefaultStyle.dp
anchors.bottomMargin: 10 * DefaultStyle.dp
AccountProxy{
id: accounts
}
account: accounts.defaultAccount
enablePersonalCamera: mainWindow.call.core.cameraEnabled
MovableMouseArea {
id: previewMouseArea
anchors.fill: parent
// visible: mainWindow.participantCount <= 2
movableArea: centerItem
margin: 10 * DefaultStyle.dp
function resetPosition(){
preview.anchors.right = centerItem.right
preview.anchors.bottom = centerItem.bottom
preview.anchors.rightMargin = previewMouseArea.margin
preview.anchors.bottomMargin = previewMouseArea.margin
}
onVisibleChanged: if(!visible){
resetPosition()
}
drag.target: preview
onDraggingChanged: if(dragging) {
preview.anchors.right = undefined
preview.anchors.bottom = undefined
}
onRequestResetPosition: resetPosition()
}
}
property int previousWidth
Component.onCompleted: {
previousWidth = width
}
onWidthChanged: {
if (width < previousWidth) {
previewMouseArea.updatePosition(0, 0)
} else {
previewMouseArea.updatePosition(width - previousWidth, 0)
}
previousWidth = width
} }
} }
} }
@ -837,9 +781,10 @@ Window {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
layoutDirection: Qt.LeftToRight layoutDirection: Qt.LeftToRight
columnSpacing: 20 * DefaultStyle.dp columnSpacing: 20 * DefaultStyle.dp
visible: mainWindow.conferenceUri ? mainWindow.conferenceJoined : mainWindow.call
function refreshLayout() { function refreshLayout() {
if (mainWindow.call.core.state === LinphoneEnums.CallState.Connected || mainWindow.call.core.state === LinphoneEnums.CallState.StreamsRunning) { if (mainWindow.callState === LinphoneEnums.CallState.Connected || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning) {
bottomButtonsLayout.layoutDirection = Qt.RightToLeft bottomButtonsLayout.layoutDirection = Qt.RightToLeft
connectedCallButtons.visible = true connectedCallButtons.visible = true
videoCameraButton.enabled = true videoCameraButton.enabled = true
@ -867,11 +812,11 @@ Window {
Layout.row: 0 Layout.row: 0
enabledIcon: AppIcons.endCall enabledIcon: AppIcons.endCall
checkable: false checkable: false
Layout.column: mainWindow.call.core.state == LinphoneEnums.CallState.OutgoingInit Layout.column: mainWindow.callState == LinphoneEnums.CallState.OutgoingInit
|| mainWindow.call.core.state == LinphoneEnums.CallState.OutgoingProgress || mainWindow.callState == LinphoneEnums.CallState.OutgoingProgress
|| mainWindow.call.core.state == LinphoneEnums.CallState.OutgoingRinging || mainWindow.callState == LinphoneEnums.CallState.OutgoingRinging
|| mainWindow.call.core.state == LinphoneEnums.CallState.OutgoingEarlyMedia || mainWindow.callState == LinphoneEnums.CallState.OutgoingEarlyMedia
|| mainWindow.call.core.state == LinphoneEnums.CallState.IncomingReceived || mainWindow.callState == LinphoneEnums.CallState.IncomingReceived
? 0 : bottomButtonsLayout.columns - 1 ? 0 : bottomButtonsLayout.columns - 1
Layout.preferredWidth: 75 * DefaultStyle.dp Layout.preferredWidth: 75 * DefaultStyle.dp
Layout.preferredHeight: 55 * DefaultStyle.dp Layout.preferredHeight: 55 * DefaultStyle.dp
@ -905,9 +850,9 @@ Window {
: DefaultStyle.grey_500 : DefaultStyle.grey_500
: DefaultStyle.grey_600 : DefaultStyle.grey_600
} }
enabled: mainWindow.call.core.state != LinphoneEnums.CallState.PausedByRemote enabled: mainWindow.callState != LinphoneEnums.CallState.PausedByRemote
enabledIcon: enabled && checked ? AppIcons.play : AppIcons.pause enabledIcon: enabled && checked ? AppIcons.play : AppIcons.pause
checked: mainWindow.call.core.paused checked: mainWindow.call && mainWindow.call.core.paused
onClicked: { onClicked: {
mainWindow.call.core.lSetPaused(!callsModel.currentCall.core.paused) mainWindow.call.core.lSetPaused(!callsModel.currentCall.core.paused)
} }
@ -945,17 +890,17 @@ Window {
} }
RowLayout { RowLayout {
Layout.row: 0 Layout.row: 0
Layout.column: mainWindow.call.core.state == LinphoneEnums.CallState.OutgoingInit Layout.column: mainWindow.callState == LinphoneEnums.CallState.OutgoingInit
|| mainWindow.call.core.state == LinphoneEnums.CallState.OutgoingProgress || mainWindow.callState == LinphoneEnums.CallState.OutgoingProgress
|| mainWindow.call.core.state == LinphoneEnums.CallState.OutgoingRinging || mainWindow.callState == LinphoneEnums.CallState.OutgoingRinging
|| mainWindow.call.core.state == LinphoneEnums.CallState.OutgoingEarlyMedia || mainWindow.callState == LinphoneEnums.CallState.OutgoingEarlyMedia
|| mainWindow.call.core.state == LinphoneEnums.CallState.IncomingReceived || mainWindow.callState == LinphoneEnums.CallState.IncomingReceived
? bottomButtonsLayout.columns - 1 : 0 ? bottomButtonsLayout.columns - 1 : 0
BottomButton { BottomButton {
id: videoCameraButton id: videoCameraButton
enabledIcon: AppIcons.videoCamera enabledIcon: AppIcons.videoCamera
disabledIcon: AppIcons.videoCameraSlash disabledIcon: AppIcons.videoCameraSlash
checked: !mainWindow.call.core.cameraEnabled checked: mainWindow.call && !mainWindow.call.core.cameraEnabled
Layout.preferredWidth: 55 * DefaultStyle.dp Layout.preferredWidth: 55 * DefaultStyle.dp
Layout.preferredHeight: 55 * DefaultStyle.dp Layout.preferredHeight: 55 * DefaultStyle.dp
onClicked: mainWindow.call.core.lSetCameraEnabled(!mainWindow.call.core.cameraEnabled) onClicked: mainWindow.call.core.lSetCameraEnabled(!mainWindow.call.core.cameraEnabled)
@ -963,7 +908,7 @@ Window {
BottomButton { BottomButton {
enabledIcon: AppIcons.microphone enabledIcon: AppIcons.microphone
disabledIcon: AppIcons.microphoneSlash disabledIcon: AppIcons.microphoneSlash
checked: mainWindow.call.core.microphoneMuted checked: mainWindow.call && mainWindow.call.core.microphoneMuted
Layout.preferredWidth: 55 * DefaultStyle.dp Layout.preferredWidth: 55 * DefaultStyle.dp
Layout.preferredHeight: 55 * DefaultStyle.dp Layout.preferredHeight: 55 * DefaultStyle.dp
onClicked: mainWindow.call.core.lSetMicrophoneMuted(!mainWindow.call.core.microphoneMuted) onClicked: mainWindow.call.core.lSetMicrophoneMuted(!mainWindow.call.core.microphoneMuted)
@ -1037,7 +982,7 @@ Window {
Button { Button {
id: recordButton id: recordButton
Layout.fillWidth: true Layout.fillWidth: true
enabled: mainWindow.call.core.recordable enabled: mainWindow.call && mainWindow.call.core.recordable
checkable: true checkable: true
background: Item {} background: Item {}
contentItem: RowLayout { contentItem: RowLayout {
@ -1046,16 +991,16 @@ Window {
Layout.preferredHeight: 24 * DefaultStyle.dp Layout.preferredHeight: 24 * DefaultStyle.dp
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
imageSource: AppIcons.recordFill imageSource: AppIcons.recordFill
colorizationColor: mainWindow.call.core.recording ? DefaultStyle.danger_500main : undefined colorizationColor: mainWindow.call && mainWindow.call.core.recording ? DefaultStyle.danger_500main : undefined
} }
Text { Text {
color: mainWindow.call.core.recording ? DefaultStyle.danger_500main : DefaultStyle.main2_600 color: mainWindow.call && mainWindow.call.core.recording ? DefaultStyle.danger_500main : DefaultStyle.main2_600
text: mainWindow.call.core.recording ? qsTr("Terminer l'enregistrement") : qsTr("Enregistrer l'appel") text: mainWindow.call && mainWindow.call.core.recording ? qsTr("Terminer l'enregistrement") : qsTr("Enregistrer l'appel")
} }
} }
onClicked: { onClicked: {
mainWindow.call.core.recording ? mainWindow.call.core.lStopRecording() : mainWindow.call.core.lStartRecording() mainWindow.call && mainWindow.call.core.recording ? mainWindow.call.core.lStopRecording() : mainWindow.call.core.lStartRecording()
} }
} }
Control.Button { Control.Button {
@ -1069,11 +1014,11 @@ Window {
Layout.preferredHeight: 24 * DefaultStyle.dp Layout.preferredHeight: 24 * DefaultStyle.dp
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
imageSource: AppIcons.recordFill imageSource: AppIcons.recordFill
colorizationColor: mainWindow.call.core.recording ? DefaultStyle.danger_500main : undefined colorizationColor: mainWindow.call && mainWindow.call.core.recording ? DefaultStyle.danger_500main : undefined
} }
Text { Text {
color: mainWindow.call.core.recording ? DefaultStyle.danger_500main : DefaultStyle.main2_600 color: mainWindow.call && mainWindow.call.core.recording ? DefaultStyle.danger_500main : DefaultStyle.main2_600
text: mainWindow.call.core.recording ? qsTr("Terminer l'enregistrement") : qsTr("Enregistrer l'appel") text: mainWindow.call && mainWindow.call.core.recording ? qsTr("Terminer l'enregistrement") : qsTr("Enregistrer l'appel")
} }
} }

View file

@ -127,6 +127,7 @@ Item {
id: topRow id: topRow
Layout.leftMargin: 25 * DefaultStyle.dp Layout.leftMargin: 25 * DefaultStyle.dp
Layout.rightMargin: 41 * DefaultStyle.dp Layout.rightMargin: 41 * DefaultStyle.dp
spacing: 25 * DefaultStyle.dp
SearchBar { SearchBar {
id: magicSearchBar id: magicSearchBar
Layout.fillWidth: true Layout.fillWidth: true
@ -263,74 +264,77 @@ Item {
} }
} }
} }
PopupButton { RowLayout {
id: avatarButton spacing: 10 * DefaultStyle.dp
AccountProxy{ PopupButton {
id: accountProxy id: avatarButton
//property bool haveAvatar: defaultAccount && defaultAccount.core.pictureUri || false AccountProxy{
} id: accountProxy
background.visible: false //property bool haveAvatar: defaultAccount && defaultAccount.core.pictureUri || false
Layout.preferredWidth: 54 * DefaultStyle.dp }
Layout.preferredHeight: width background.visible: false
contentItem: Avatar { Layout.preferredWidth: 54 * DefaultStyle.dp
id: avatar Layout.preferredHeight: width
height: avatarButton.height contentItem: Avatar {
width: avatarButton.width id: avatar
account: accountProxy.defaultAccount height: avatarButton.height
} width: avatarButton.width
popup.x: width - popup.width account: accountProxy.defaultAccount
popup.padding: 0 }
popup.contentItem: ColumnLayout { popup.x: width - popup.width
Accounts { popup.padding: 0
id: accounts popup.contentItem: ColumnLayout {
onAddAccountRequest: mainItem.addAccountRequest() Accounts {
id: accounts
onAddAccountRequest: mainItem.addAccountRequest()
}
} }
} }
} PopupButton {
PopupButton { id: settingsButton
id: settingsButton Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredWidth: 24 * DefaultStyle.dp Layout.preferredHeight: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp popup.x: width - popup.width
popup.x: width - popup.width popup.width: 271 * DefaultStyle.dp
popup.width: 271 * DefaultStyle.dp popup.contentItem: ColumnLayout {
popup.contentItem: ColumnLayout { spacing: 20 * DefaultStyle.dp
spacing: 20 * DefaultStyle.dp IconLabelButton {
IconLabelButton { Layout.preferredHeight: 32 * DefaultStyle.dp
Layout.preferredHeight: 32 * DefaultStyle.dp iconSize: 32 * DefaultStyle.dp
iconSize: 32 * DefaultStyle.dp text: qsTr("Mon compte")
text: qsTr("Mon compte") iconSource: AppIcons.manageProfile
iconSource: AppIcons.manageProfile onClicked: console.log("TODO : manage profile")
onClicked: console.log("TODO : manage profile") }
} IconLabelButton {
IconLabelButton { Layout.preferredHeight: 32 * DefaultStyle.dp
Layout.preferredHeight: 32 * DefaultStyle.dp iconSize: 32 * DefaultStyle.dp
iconSize: 32 * DefaultStyle.dp text: qsTr("Paramètres")
text: qsTr("Paramètres") iconSource: AppIcons.settings
iconSource: AppIcons.settings }
} IconLabelButton {
IconLabelButton { Layout.preferredHeight: 32 * DefaultStyle.dp
Layout.preferredHeight: 32 * DefaultStyle.dp iconSize: 32 * DefaultStyle.dp
iconSize: 32 * DefaultStyle.dp text: qsTr("Enregistrements")
text: qsTr("Enregistrements") iconSource: AppIcons.micro
iconSource: AppIcons.micro }
} IconLabelButton {
IconLabelButton { Layout.preferredHeight: 32 * DefaultStyle.dp
Layout.preferredHeight: 32 * DefaultStyle.dp iconSize: 32 * DefaultStyle.dp
iconSize: 32 * DefaultStyle.dp text: qsTr("Aide")
text: qsTr("Aide") iconSource: AppIcons.question
iconSource: AppIcons.question }
} Rectangle {
Rectangle { Layout.fillWidth: true
Layout.fillWidth: true Layout.preferredHeight: 1 * DefaultStyle.dp
Layout.preferredHeight: 1 * DefaultStyle.dp color: DefaultStyle.main2_400
color: DefaultStyle.main2_400 }
} IconLabelButton {
IconLabelButton { Layout.preferredHeight: 32 * DefaultStyle.dp
Layout.preferredHeight: 32 * DefaultStyle.dp iconSize: 32 * DefaultStyle.dp
iconSize: 32 * DefaultStyle.dp text: qsTr("Ajouter un compte")
text: qsTr("Ajouter un compte") iconSource: AppIcons.plusCircle
iconSource: AppIcons.plusCircle onClicked: mainItem.addAccountRequest()
onClicked: mainItem.addAccountRequest() }
} }
} }
} }

View file

@ -16,7 +16,9 @@ list(APPEND _LINPHONEAPP_QML_FILES
view/Item/Account/Accounts.qml view/Item/Account/Accounts.qml
view/Item/Call/CallContactsLists.qml view/Item/Call/CallContactsLists.qml
view/Item/Call/InCallSettingsPanel.qml
view/Item/Call/OngoingCallRightPanel.qml view/Item/Call/OngoingCallRightPanel.qml
view/Item/Call/WaitingRoom.qml
view/Item/Notification/Notification.qml view/Item/Notification/Notification.qml
view/Item/Notification/NotificationReceivedCall.qml view/Item/Notification/NotificationReceivedCall.qml
@ -38,6 +40,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
view/Item/Calendar.qml view/Item/Calendar.qml
view/Item/CalendarComboBox.qml view/Item/CalendarComboBox.qml
view/Item/Carousel.qml view/Item/Carousel.qml
view/Item/CheckableButton.qml
view/Item/CheckBox.qml view/Item/CheckBox.qml
view/Item/ComboBox.qml view/Item/ComboBox.qml
view/Item/DesktopPopup.qml view/Item/DesktopPopup.qml

View file

@ -1,5 +1,5 @@
import QtQuick 2.7 import QtQuick
import QtQuick.Controls 2.2 as Control import QtQuick.Controls as Control
import QtQuick.Effects import QtQuick.Effects
import Linphone import Linphone
@ -13,11 +13,20 @@ Item {
id: busyIndicator id: busyIndicator
running: mainItem.visible running: mainItem.visible
anchors.centerIn: mainItem anchors.centerIn: mainItem
} contentItem: EffectImage {
MultiEffect { id: busyImage
source: busyIndicator imageWidth: mainItem.width
anchors.fill: busyIndicator imageHeight: mainItem.height
colorizationColor: mainItem.indicatorColor imageSource: AppIcons.busyIndicator
colorization: 1.0 colorizationColor: mainItem.indicatorColor
RotationAnimator {
target: busyImage
running: busyIndicator.running
from: 0
to: 360
loops: Animation.Infinite
duration: 10000
}
}
} }
} }

View file

@ -44,7 +44,7 @@ Control.Button {
? mainItem.pressedColor ? mainItem.pressedColor
: mainItem.color : mainItem.color
radius: 48 * DefaultStyle.dp radius: 48 * DefaultStyle.dp
border.color: inversedColors ? mainItem.color : DefaultStyle.grey_0 border.color: inversedColors ? mainItem.color : "transparent"
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent

View file

@ -0,0 +1,169 @@
import QtQuick
import QtQuick.Controls as Control
import QtQuick.Layouts
import Linphone
import SettingsCpp 1.0
ColumnLayout {
id: mainItem
property CallGui call
onCallChanged: {
if (call) {
console.log("============================== volume ", speakerVolume.value, microVolume.value)
call.core.lSetOutputAudioDevice(outputAudioDeviceCBox.currentText)
call.core.lSetSpeakerVolumeGain(speakerVolume.value)
call.core.lSetInputAudioDevice(inputAudioDeviceCBox.currentText)
call.core.lSetMicrophoneVolumeGain(microVolume.value)
}
}
RoundedBackgroundControl {
Layout.alignment: Qt.AlignHCenter
Control.StackView.onActivated: {
rightPanelTitle.text = qsTr("Paramètres")
}
backgroundColor: DefaultStyle.main2_0
height: contentItem.implicitHeight + topPadding + bottomPadding
Layout.fillWidth: true
topPadding: 25 * DefaultStyle.dp
bottomPadding: 25 * DefaultStyle.dp
leftPadding: 25 * DefaultStyle.dp
rightPadding: 25 * DefaultStyle.dp
contentItem: ColumnLayout {
spacing: 10 * DefaultStyle.dp
RowLayout {
Layout.fillWidth: true
EffectImage {
imageSource: AppIcons.speaker
colorizationColor: DefaultStyle.main1_500_main
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
imageWidth: 24 * DefaultStyle.dp
imageHeight: 24 * DefaultStyle.dp
}
Text {
text: qsTr("Haut-parleurs")
Layout.fillWidth: true
}
}
ComboBox {
id: outputAudioDeviceCBox
Layout.fillWidth: true
Layout.preferredWidth: parent.width
Layout.preferredHeight: 49 * DefaultStyle.dp
model: SettingsCpp.outputAudioDevicesList
onCurrentTextChanged: {
if (mainItem.call) mainItem.call.core.lSetOutputAudioDevice(currentText)
}
}
Slider {
id: speakerVolume
Layout.fillWidth: true
from: 0.0
to: 1.0
value: mainItem.call ? mainItem.call.core.speakerVolumeGain : 0.5
onMoved: {
if (mainItem.call) mainItem.call.core.lSetSpeakerVolumeGain(value)
}
}
RowLayout {
Layout.fillWidth: true
EffectImage {
imageSource: AppIcons.microphone
colorizationColor: DefaultStyle.main1_500_main
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
imageWidth: 24 * DefaultStyle.dp
imageHeight: 24 * DefaultStyle.dp
}
Text {
text: qsTr("Microphone")
Layout.fillWidth: true
}
}
ComboBox {
id: inputAudioDeviceCBox
Layout.fillWidth: true
Layout.preferredWidth: parent.width
Layout.preferredHeight: 49 * DefaultStyle.dp
model: SettingsCpp.inputAudioDevicesList
onCurrentTextChanged: {
if (mainItem.call) mainItem.call.core.lSetInputAudioDevice(currentText)
}
}
Slider {
id: microVolume
Layout.fillWidth: true
from: 0.0
to: 1.0
value: mainItem.call ? mainItem.call.core.microphoneVolumeGain : 0.5
onMoved: {
if (mainItem.call) mainItem.call.core.lSetMicrophoneVolumeGain(value)
}
}
Timer {
interval: 50
repeat: true
running: mainItem.call || false
onTriggered: audioTestSlider.value = (mainItem.call && mainItem.call.core.microVolume)
}
Slider {
id: audioTestSlider
Layout.fillWidth: true
enabled: false
Layout.preferredHeight: 10 * DefaultStyle.dp
background: Rectangle {
x: audioTestSlider.leftPadding
y: audioTestSlider.topPadding + audioTestSlider.availableHeight / 2 - height / 2
implicitWidth: 200 * DefaultStyle.dp
implicitHeight: 10 * DefaultStyle.dp
width: audioTestSlider.availableWidth
height: implicitHeight
radius: 2 * DefaultStyle.dp
color: "#D9D9D9"
Rectangle {
width: audioTestSlider.visualPosition * parent.width
height: parent.height
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: "#6FF88D" }
GradientStop { position: 1.0; color: "#00D916" }
}
radius: 2 * DefaultStyle.dp
}
}
handle: Item {visible: false}
}
RowLayout {
Layout.fillWidth: true
EffectImage {
imageSource: AppIcons.videoCamera
colorizationColor: DefaultStyle.main1_500_main
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
imageWidth: 24 * DefaultStyle.dp
imageHeight: 24 * DefaultStyle.dp
}
Text {
text: qsTr("Caméra")
Layout.fillWidth: true
}
}
ComboBox {
Layout.fillWidth: true
Layout.preferredWidth: parent.width
Layout.preferredHeight: 49 * DefaultStyle.dp
model: SettingsCpp.videoDevicesList
currentIndex: SettingsCpp.currentVideoDeviceIndex
onCurrentTextChanged: {
SettingsCpp.lSetVideoDevice(currentText)
}
}
}
}
Item {
Layout.fillHeight: true
}
}

View file

@ -17,6 +17,9 @@ Control.Page {
header: Control.Control { header: Control.Control {
id: pageHeader id: pageHeader
width: mainItem.width width: mainItem.width
height: 56 * DefaultStyle.dp
leftPadding: 10 * DefaultStyle.dp
rightPadding: 10 * DefaultStyle.dp
background: Rectangle { background: Rectangle {
id: headerBackground id: headerBackground
width: pageHeader.width width: pageHeader.width
@ -30,19 +33,13 @@ Control.Page {
} }
} }
contentItem: RowLayout { contentItem: RowLayout {
width: pageHeader.width
height: pageHeader.height
anchors.leftMargin: 10 * DefaultStyle.dp
anchors.left: pageHeader.left
Item { Item {
id: header id: header
}
Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true
} }
Button { Button {
id: closeButton id: closeButton
Layout.alignment: Qt.AlignRight
background: Item { background: Item {
visible: false visible: false
} }

View file

@ -0,0 +1,149 @@
import QtQuick 2.15
import QtQuick.Layouts
import QtQuick.Effects
import QtQuick.Controls as Control
import Linphone
import UtilsCpp 1.0
RowLayout {
id: mainItem
property bool cameraEnabled: true
property bool microEnabled: true
property bool settingsButtonChecked: settingsButton.checked
property ConferenceInfoGui conferenceInfo
signal joinConfRequested()
RowLayout {
Layout.fillWidth: false
Layout.fillHeight: false
spacing: 100 * DefaultStyle.dp
Layout.alignment: Qt.AlignCenter
ColumnLayout {
spacing: 31 * DefaultStyle.dp
// Layout.leftMargin: 97 * DefaultStyle.dp
Sticker {
id: preview
Layout.preferredHeight: 330 * DefaultStyle.dp
Layout.preferredWidth: 558 * DefaultStyle.dp
AccountProxy{
id: accounts
}
account: accounts.defaultAccount
enablePersonalCamera: mainItem.cameraEnabled
}
RowLayout {
Layout.alignment: Qt.AlignHCenter
CheckableButton {
id: videoButton
iconUrl: AppIcons.videoCamera
checkedIconUrl: AppIcons.videoCameraSlash
color: DefaultStyle.grey_500
contentImageColor: DefaultStyle.main2_0
Layout.preferredWidth: 55 * DefaultStyle.dp
Layout.preferredHeight: 55 * DefaultStyle.dp
onCheckedChanged: mainItem.cameraEnabled = !mainItem.cameraEnabled
}
CheckableButton {
id: microButton
iconUrl: AppIcons.microphone
checkedIconUrl: AppIcons.microphoneSlash
color: DefaultStyle.grey_500
contentImageColor: DefaultStyle.main2_0
Layout.preferredWidth: 55 * DefaultStyle.dp
Layout.preferredHeight: 55 * DefaultStyle.dp
onCheckedChanged: mainItem.microEnabled = !mainItem.microEnabled
}
CheckableButton {
id: settingsButton
visible: stackLayout.currentIndex === 0
icon.source: AppIcons.more
color: DefaultStyle.grey_500
checkedColor: DefaultStyle.main2_100
contentImageColor: checked ? DefaultStyle.grey_500 : DefaultStyle.grey_0
Layout.preferredWidth: 55 * DefaultStyle.dp
Layout.preferredHeight: 55 * DefaultStyle.dp
}
CheckableButton {
id: speakerButton
visible: stackLayout.currentIndex === 1
iconUrl: AppIcons.speaker
checkedIconUrl: AppIcons.speakerSlash
color: DefaultStyle.grey_500
contentImageColor: checked ? DefaultStyle.grey_500 : DefaultStyle.grey_0
Layout.preferredWidth: 55 * DefaultStyle.dp
Layout.preferredHeight: 55 * DefaultStyle.dp
}
}
}
StackLayout {
id: stackLayout
currentIndex: 0
ColumnLayout {
spacing: 93 * DefaultStyle.dp
ColumnLayout {
spacing: 5 * DefaultStyle.dp
Text {
Layout.fillWidth: true
text: qsTr("Participer à :\n")
color: DefaultStyle.grey_0
font {
pixelSize: 30 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
}
Text {
Layout.fillWidth: true
text: mainItem.conferenceInfo && mainItem.conferenceInfo.core.subject
color: DefaultStyle.grey_0
font {
pixelSize: 30 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
}
}
Button {
Layout.preferredWidth: 292 * DefaultStyle.dp
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
topPadding: 11 * DefaultStyle.dp
bottomPadding: 11 * DefaultStyle.dp
text: qsTr("Join")
onClicked: {
settingsButton.checked = false
stackLayout.currentIndex = 1
mainItem.joinConfRequested()
}
}
}
ColumnLayout {
spacing: 37 * DefaultStyle.dp
ColumnLayout {
spacing: 13 * DefaultStyle.dp
Text {
Layout.fillWidth: true
text: qsTr("Connexion à la réunion")
color: DefaultStyle.grey_0
font {
pixelSize: 30 * DefaultStyle.dp
weight: 300 * DefaultStyle.dp
}
}
Text {
Layout.fillWidth: true
text: qsTr("Vous allez rejoindre la réunion dans quelques instants...")
color: DefaultStyle.grey_0
font {
pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
}
}
BusyIndicator {
indicatorColor: DefaultStyle.main1_500_main
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 48 * DefaultStyle.dp
Layout.preferredHeight: 48 * DefaultStyle.dp
}
}
}
}
}

View file

@ -0,0 +1,31 @@
import QtQuick 2.15
import QtQuick.Layouts
import QtQuick.Effects
import QtQuick.Controls as Control
import Linphone
Button {
id: mainItem
property string iconUrl
property string checkedIconUrl
property color color: DefaultStyle.grey_500
property color checkedColor: DefaultStyle.main2_400
leftPadding: 0
rightPadding: 0
topPadding: 0
bottomPadding: 0
checkable: true
background: Rectangle {
anchors.fill: parent
color: mainItem.enabled
? mainItem.pressed || mainItem.checked
? mainItem.checkedColor
: mainItem.color
: DefaultStyle.grey_600
radius: mainItem.width * 1.29
}
icon.source: checkedIconUrl && mainItem.checked ? checkedIconUrl : iconUrl
icon.width: width * 0.58
icon.height: width * 0.58
contentImageColor: enabled ? DefaultStyle.grey_0 : DefaultStyle.grey_500
}

View file

@ -53,6 +53,7 @@ Popup {
contentItem: ColumnLayout { contentItem: ColumnLayout {
spacing: 20 * DefaultStyle.dp spacing: 20 * DefaultStyle.dp
ColumnLayout { ColumnLayout {
id: contentLayout id: contentLayout
Layout.fillWidth: true Layout.fillWidth: true
@ -64,6 +65,7 @@ Popup {
visible: text.length != 0 visible: text.length != 0
width: parent.width width: parent.width
Layout.preferredWidth: 278 * DefaultStyle.dp Layout.preferredWidth: 278 * DefaultStyle.dp
Layout.alignment: Qt.AlignCenter
text: mainItem.text text: mainItem.text
font { font {
pixelSize: 14 * DefaultStyle.dp pixelSize: 14 * DefaultStyle.dp

View file

@ -91,8 +91,8 @@ ColumnLayout {
color: DefaultStyle.grey_0 color: DefaultStyle.grey_0
} }
BusyIndicator { BusyIndicator {
width: parent.height implicitWidth: parent.height
height: parent.height implicitHeight: parent.height
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
indicatorColor: DefaultStyle.grey_0 indicatorColor: DefaultStyle.grey_0
} }

View file

@ -25,9 +25,14 @@ ListView {
onCountChanged: selectedConference = model.getAt(currentIndex) || null onCountChanged: selectedConference = model.getAt(currentIndex) || null
onCurrentIndexChanged: selectedConference = model.getAt(currentIndex) || null onCurrentIndexChanged: selectedConference = model.getAt(currentIndex) || null
function forceUpdate() {
confInfoProxy.lUpdate()
}
signal conferenceSelected(var contact) signal conferenceSelected(var contact)
model: ConferenceInfoProxy { model: ConferenceInfoProxy {
id: confInfoProxy
searchText: searchBarText.length === 0 ? "" : searchBarText searchText: searchBarText.length === 0 ? "" : searchBarText
} }

View file

@ -12,13 +12,15 @@ ColumnLayout {
property ConferenceInfoGui conferenceInfoGui property ConferenceInfoGui conferenceInfoGui
signal addParticipantsRequested() signal addParticipantsRequested()
signal returnRequested() signal returnRequested()
signal creationSucceed() signal saveSucceed(bool isCreation)
Connections { Connections {
target: mainItem.conferenceInfoGui.core target: mainItem.conferenceInfoGui.core
onSchedulerStateChanged: { onSchedulerStateChanged: {
if (isCreation && mainItem.conferenceInfoGui.core.schedulerState == LinphoneEnums.ConferenceSchedulerState.Ready) mainItem.creationSucceed()
console.log("scheduler state changed", mainItem.conferenceInfoGui.core.schedulerState) console.log("scheduler state changed", mainItem.conferenceInfoGui.core.schedulerState)
if (mainItem.conferenceInfoGui.core.schedulerState == LinphoneEnums.ConferenceSchedulerState.Ready) {
mainItem.saveSucceed(isCreation)
}
} }
} }
@ -181,6 +183,7 @@ ColumnLayout {
CalendarComboBox { CalendarComboBox {
id: startDate id: startDate
background.visible: mainItem.isCreation background.visible: mainItem.isCreation
indicator.visible: mainItem.isCreation
contentText.font.weight: (isCreation ? 700 : 400) * DefaultStyle.dp contentText.font.weight: (isCreation ? 700 : 400) * DefaultStyle.dp
Layout.preferredWidth: 200 * DefaultStyle.dp Layout.preferredWidth: 200 * DefaultStyle.dp
Layout.preferredHeight: 30 * DefaultStyle.dp Layout.preferredHeight: 30 * DefaultStyle.dp
@ -197,6 +200,7 @@ ColumnLayout {
TimeComboBox { TimeComboBox {
id: startHour id: startHour
visible: allDaySwitch.position === 0 visible: allDaySwitch.position === 0
indicator.visible: mainItem.isCreation
// Layout.fillWidth: true // Layout.fillWidth: true
Layout.preferredWidth: 94 * DefaultStyle.dp Layout.preferredWidth: 94 * DefaultStyle.dp
Layout.preferredHeight: 30 * DefaultStyle.dp Layout.preferredHeight: 30 * DefaultStyle.dp
@ -218,6 +222,7 @@ ColumnLayout {
CalendarComboBox { CalendarComboBox {
id: endDate id: endDate
background.visible: mainItem.isCreation background.visible: mainItem.isCreation
indicator.visible: mainItem.isCreation
// Layout.fillWidth: true // Layout.fillWidth: true
Layout.preferredWidth: 200 * DefaultStyle.dp Layout.preferredWidth: 200 * DefaultStyle.dp
Layout.preferredHeight: 30 * DefaultStyle.dp Layout.preferredHeight: 30 * DefaultStyle.dp
@ -228,6 +233,7 @@ ColumnLayout {
TimeComboBox { TimeComboBox {
id: endHour id: endHour
visible: allDaySwitch.position === 0 visible: allDaySwitch.position === 0
indicator.visible: mainItem.isCreation
Layout.preferredWidth: 94 * DefaultStyle.dp Layout.preferredWidth: 94 * DefaultStyle.dp
Layout.preferredHeight: 30 * DefaultStyle.dp Layout.preferredHeight: 30 * DefaultStyle.dp
background.visible: mainItem.isCreation background.visible: mainItem.isCreation

View file

@ -22,7 +22,8 @@ Dialog {
onCallChanged: if(!call) close() onCallChanged: if(!call) close()
Connections { Connections {
target: call.core enabled: call != undefined && call != null
target: call && call.core
onStatusChanged: if (status === CallModel.CallStatusEnded) close() onStatusChanged: if (status === CallModel.CallStatusEnded) close()
} }
@ -98,7 +99,8 @@ Dialog {
property var correctIndex property var correctIndex
property var modelList property var modelList
Connections { Connections {
target: mainItem.call.core enabled: mainItem.call
target: mainItem.call ? mainItem.call.core : null
// this connection is needed to get the remoteSas when available // this connection is needed to get the remoteSas when available
// due to the asynchronous connection between core and ui // due to the asynchronous connection between core and ui
onRemoteSasChanged: { onRemoteSasChanged: {

View file

@ -44,6 +44,7 @@ AbstractMainPage {
id: leftPanel id: leftPanel
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Control.StackView { Control.StackView {
id: listStackView id: listStackView
clip: true clip: true
@ -57,6 +58,7 @@ AbstractMainPage {
id: historyListItem id: historyListItem
ColumnLayout { ColumnLayout {
spacing: 30 * DefaultStyle.dp
property alias listView: historyListView property alias listView: historyListView
RowLayout { RowLayout {
spacing: 16 * DefaultStyle.dp spacing: 16 * DefaultStyle.dp
@ -211,25 +213,37 @@ AbstractMainPage {
} }
RowLayout { RowLayout {
spacing: 3 * DefaultStyle.dp spacing: 3 * DefaultStyle.dp
Image { EffectImage {
source: modelData.core.status === LinphoneEnums.CallStatus.Declined id: statusIcon
imageSource: modelData.core.status === LinphoneEnums.CallStatus.Declined
|| 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
? modelData.core.isOutgoing ? AppIcons.arrowElbow
? AppIcons.outgoingCallRejected : modelData.core.isOutgoing
: AppIcons.incomingCallRejected ? AppIcons.arrowUpRight
: modelData.core.status === LinphoneEnums.CallStatus.Missed : AppIcons.arrowDownLeft
? modelData.core.isOutgoing colorizationColor: modelData.core.status === LinphoneEnums.CallStatus.Declined
? AppIcons.outgoingCallMissed || modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
: AppIcons.incomingCallMissed || modelData.core.status === LinphoneEnums.CallStatus.Aborted
: modelData.core.isOutgoing || modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted
? AppIcons.outgoingCall || modelData.core.status === LinphoneEnums.CallStatus.Missed
: AppIcons.incomingCall ? DefaultStyle.danger_500main
Layout.preferredWidth: 5 * DefaultStyle.dp : modelData.core.isOutgoing
Layout.preferredHeight: 5 * DefaultStyle.dp ? DefaultStyle.info_500_main
sourceSize.width: 5 * DefaultStyle.dp : DefaultStyle.success_500main
sourceSize.height: 5 * DefaultStyle.dp Layout.preferredWidth: 12 * DefaultStyle.dp
Layout.preferredHeight: 12 * DefaultStyle.dp
transform: Rotation {
angle: modelData.core.isOutgoing && (modelData.core.status === LinphoneEnums.CallStatus.Declined
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted) ? 180 : 0
origin {
x: statusIcon.width/2
y: statusIcon.height/2
}
}
} }
Text { Text {
// text: modelData.core.date // text: modelData.core.date
@ -309,6 +323,7 @@ AbstractMainPage {
Component { Component {
id: newCallItem id: newCallItem
ColumnLayout { ColumnLayout {
spacing: 30 * DefaultStyle.dp
RowLayout { RowLayout {
Layout.leftMargin: listStackView.sideMargin Layout.leftMargin: listStackView.sideMargin
Layout.rightMargin: listStackView.sideMargin Layout.rightMargin: listStackView.sideMargin
@ -465,25 +480,37 @@ AbstractMainPage {
ColumnLayout { ColumnLayout {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
RowLayout { RowLayout {
Image { EffectImage {
source: modelData.core.status === LinphoneEnums.CallStatus.Declined id: statusIcon
imageSource: modelData.core.status === LinphoneEnums.CallStatus.Declined
|| 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
? modelData.core.isOutgoing ? AppIcons.arrowElbow
? AppIcons.outgoingCallRejected : modelData.core.isOutgoing
: AppIcons.incomingCallRejected ? AppIcons.arrowUpRight
: modelData.core.status === LinphoneEnums.CallStatus.Missed : AppIcons.arrowDownLeft
? modelData.core.isOutgoing colorizationColor: modelData.core.status === LinphoneEnums.CallStatus.Declined
? AppIcons.outgoingCallMissed || modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
: AppIcons.incomingCallMissed || modelData.core.status === LinphoneEnums.CallStatus.Aborted
: modelData.core.isOutgoing || modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted
? AppIcons.outgoingCall || modelData.core.status === LinphoneEnums.CallStatus.Missed
: AppIcons.incomingCall ? DefaultStyle.danger_500main
Layout.preferredWidth: 6.67 * DefaultStyle.dp : modelData.core.isOutgoing
Layout.preferredHeight: 6.67 * DefaultStyle.dp ? DefaultStyle.info_500_main
sourceSize.width: 6.67 * DefaultStyle.dp : DefaultStyle.success_500main
sourceSize.height: 6.67 * DefaultStyle.dp Layout.preferredWidth: 16 * DefaultStyle.dp
Layout.preferredHeight: 16 * DefaultStyle.dp
transform: Rotation {
angle: modelData.core.isOutgoing && (modelData.core.status === LinphoneEnums.CallStatus.Declined
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted) ? 180 : 0
origin {
x: statusIcon.width/2
y: statusIcon.height/2
}
}
} }
Text { Text {
text: modelData.core.status === LinphoneEnums.CallStatus.Missed text: modelData.core.status === LinphoneEnums.CallStatus.Missed

View file

@ -62,6 +62,7 @@ AbstractMainPage {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
property int sideMargin: 25 * DefaultStyle.dp property int sideMargin: 25 * DefaultStyle.dp
spacing: 30 * DefaultStyle.dp
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
@ -92,7 +93,6 @@ AbstractMainPage {
} }
ColumnLayout { ColumnLayout {
Layout.topMargin: 30 * DefaultStyle.dp
Layout.leftMargin: leftPanel.sideMargin Layout.leftMargin: leftPanel.sideMargin
enabled: mainItem.leftPanelEnabled enabled: mainItem.leftPanelEnabled
SearchBar { SearchBar {

View file

@ -16,6 +16,7 @@ AbstractMainPage {
property bool leftPanelEnabled: true property bool leftPanelEnabled: true
property ConferenceInfoGui selectedConference property ConferenceInfoGui selectedConference
property int meetingListCount property int meetingListCount
signal newConfCreated()
onSelectedConferenceChanged: { onSelectedConferenceChanged: {
if (selectedConference) { if (selectedConference) {
@ -45,6 +46,52 @@ AbstractMainPage {
} }
} }
Dialog {
id: cancelAndDeleteConfDialog
property bool cancel: false
signal cancelRequested()
// width: 278 * DefaultStyle.dp
text: cancel ? qsTr("Souhaitez-vous annuler et supprimer cette réunion ?") : qsTr("Souhaitez-vous supprimer cette réunion ?")
buttons: [
Button {
visible: cancelAndDeleteConfDialog.cancel
text: qsTr("Annuler et supprimer")
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
topPadding: 11 * DefaultStyle.dp
bottomPadding: 11 * DefaultStyle.dp
onClicked: {
cancelAndDeleteConfDialog.accepted()
cancelAndDeleteConfDialog.close()
cancelAndDeleteConfDialog.cancelRequested()
}
},
Button {
text: cancelAndDeleteConfDialog.cancel ? qsTr("Supprimer seulement") : qsTr("Supprimer")
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
topPadding: 11 * DefaultStyle.dp
bottomPadding: 11 * DefaultStyle.dp
onClicked: {
cancelAndDeleteConfDialog.accepted()
cancelAndDeleteConfDialog.close()
}
},
Button {
text: qsTr("Retour")
inversedColors: true
leftPadding: 20 * DefaultStyle.dp
rightPadding: 20 * DefaultStyle.dp
topPadding: 11 * DefaultStyle.dp
bottomPadding: 11 * DefaultStyle.dp
onClicked: {
cancelAndDeleteConfDialog.rejected()
cancelAndDeleteConfDialog.close()
}
}
]
}
leftPanelContent: ColumnLayout { leftPanelContent: ColumnLayout {
id: leftPanel id: leftPanel
Layout.fillWidth: true Layout.fillWidth: true
@ -52,66 +99,59 @@ AbstractMainPage {
property int sideMargin: 25 * DefaultStyle.dp property int sideMargin: 25 * DefaultStyle.dp
ColumnLayout { ColumnLayout {
Layout.topMargin: 30 * DefaultStyle.dp // Layout.topMargin: 30 * DefaultStyle.dp
Layout.leftMargin: leftPanel.sideMargin Layout.leftMargin: leftPanel.sideMargin
spacing: 30 * DefaultStyle.dp
enabled: mainItem.leftPanelEnabled enabled: mainItem.leftPanelEnabled
RowLayout {
visible: leftPanelStackView.currentItem.objectName == "listLayout"
Layout.fillWidth: true
Layout.rightMargin: leftPanel.sideMargin
Text {
text: qsTr("Réunions")
color: DefaultStyle.main2_700
font.pixelSize: 29 * DefaultStyle.dp
font.weight: 800 * DefaultStyle.dp
}
Item {
Layout.fillWidth: true
}
Button {
background: Item {
}
icon.source: AppIcons.plusCircle
Layout.preferredWidth: 30 * DefaultStyle.dp
Layout.preferredHeight: 30 * DefaultStyle.dp
width: 30 * DefaultStyle.dp
height: 30 * DefaultStyle.dp
onClicked: {
mainItem.setUpConference()
}
}
}
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Control.ScrollBar {
id: meetingsScrollbar
visible: leftPanelStackView.currentItem.objectName == "listLayout"
active: true
interactive: true
policy: Control.ScrollBar.AsNeeded
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
}
Control.StackView { Control.StackView {
id: leftPanelStackView id: leftPanelStackView
initialItem: listLayout initialItem: listLayout
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: leftPanel.sideMargin
} }
Component { Component {
id: listLayout id: listLayout
ColumnLayout { ColumnLayout {
property string objectName: "listLayout" property string objectName: "listLayout"
spacing: 19 * DefaultStyle.dp spacing: 19 * DefaultStyle.dp
RowLayout {
Layout.fillWidth: true
Layout.leftMargin: leftPanel.sideMargin
Layout.rightMargin: leftPanel.sideMargin
Text {
text: qsTr("Réunions")
color: DefaultStyle.main2_700
font.pixelSize: 29 * DefaultStyle.dp
font.weight: 800 * DefaultStyle.dp
}
Item {
Layout.fillWidth: true
}
Button {
background: Item {
}
icon.source: AppIcons.plusCircle
Layout.preferredWidth: 30 * DefaultStyle.dp
Layout.preferredHeight: 30 * DefaultStyle.dp
width: 30 * DefaultStyle.dp
height: 30 * DefaultStyle.dp
onClicked: {
mainItem.setUpConference()
}
}
}
SearchBar { SearchBar {
id: searchBar id: searchBar
Layout.rightMargin: leftPanel.sideMargin
Layout.fillWidth: true Layout.fillWidth: true
Layout.rightMargin: leftPanel.sideMargin
placeholderText: qsTr("Rechercher une réunion") placeholderText: qsTr("Rechercher une réunion")
} }
@ -126,21 +166,40 @@ AbstractMainPage {
visible: mainItem.showDefaultItem visible: mainItem.showDefaultItem
} }
MeetingList { RowLayout {
id: conferenceList MeetingList {
visible: count != 0 id: conferenceList
hoverEnabled: mainItem.leftPanelEnabled visible: count != 0
Layout.fillWidth: true hoverEnabled: mainItem.leftPanelEnabled
Layout.fillHeight: true Layout.fillWidth: true
Layout.topMargin: 20 * DefaultStyle.dp Layout.fillHeight: true
searchBarText: searchBar.text Layout.topMargin: 20 * DefaultStyle.dp
onSelectedConferenceChanged: { searchBarText: searchBar.text
mainItem.selectedConference = selectedConference onSelectedConferenceChanged: {
mainItem.selectedConference = selectedConference
}
onCountChanged: {
mainItem.meetingListCount = count
}
Connections {
target: mainItem
onNewConfCreated: {
conferenceList.forceUpdate()
}
}
Control.ScrollBar.vertical: meetingsScrollbar
} }
onCountChanged: { Control.ScrollBar {
mainItem.meetingListCount = count id: meetingsScrollbar
visible: leftPanelStackView.currentItem.objectName == "listLayout"
active: true
interactive: true
policy: Control.ScrollBar.AsNeeded
Layout.fillHeight: true
// anchors.top: parent.top
// anchors.bottom: parent.bottom
// anchors.right: parent.right
} }
Control.ScrollBar.vertical: meetingsScrollbar
} }
} }
} }
@ -152,10 +211,14 @@ AbstractMainPage {
id: createConf id: createConf
MeetingSetUp { MeetingSetUp {
Layout.rightMargin: leftPanel.sideMargin Layout.rightMargin: leftPanel.sideMargin
onCreationSucceed: { onSaveSucceed: {
mainItem.newConfCreated()
leftPanelStackView.pop() leftPanelStackView.pop()
UtilsCpp.showInformationPopup(qsTr("Nouvelle réunion"), qsTr("Réunion planifiée avec succès"), true) UtilsCpp.showInformationPopup(qsTr("Nouvelle réunion"), qsTr("Réunion planifiée avec succès"), true)
} }
onReturnRequested: {
leftPanelStackView.pop()
}
onAddParticipantsRequested: { onAddParticipantsRequested: {
leftPanelStackView.push(addParticipants, {"conferenceInfoGui": conferenceInfoGui, "container": leftPanelStackView}) leftPanelStackView.push(addParticipants, {"conferenceInfoGui": conferenceInfoGui, "container": leftPanelStackView})
} }
@ -178,6 +241,10 @@ AbstractMainPage {
onReturnRequested: { onReturnRequested: {
mainItem.rightPanelStackView.pop() mainItem.rightPanelStackView.pop()
} }
onSaveSucceed: {
mainItem.rightPanelStackView.pop()
UtilsCpp.showInformationPopup(qsTr("Enregistré"), qsTr("Réunion modifiée avec succès"), true)
}
onAddParticipantsRequested: { onAddParticipantsRequested: {
mainItem.rightPanelStackView.push(addParticipants, {"conferenceInfoGui": conferenceInfoGui, "container": mainItem.rightPanelStackView}) mainItem.rightPanelStackView.push(addParticipants, {"conferenceInfoGui": conferenceInfoGui, "container": mainItem.rightPanelStackView})
} }
@ -200,8 +267,8 @@ AbstractMainPage {
id: meetingDetail id: meetingDetail
RowLayout { RowLayout {
ColumnLayout { ColumnLayout {
Layout.alignment: Qt.AlignTop
Layout.preferredWidth: 393 * DefaultStyle.dp Layout.preferredWidth: 393 * DefaultStyle.dp
Layout.alignment: Qt.AlignTop
Layout.fillWidth: false Layout.fillWidth: false
Layout.fillHeight: true Layout.fillHeight: true
Layout.leftMargin: 39 * DefaultStyle.dp Layout.leftMargin: 39 * DefaultStyle.dp
@ -216,7 +283,7 @@ AbstractMainPage {
Layout.preferredHeight: 24 * DefaultStyle.dp Layout.preferredHeight: 24 * DefaultStyle.dp
} }
Text { Text {
text: mainItem.selectedConference && mainItem.selectedConference.core.subject text: mainItem.selectedConference ? mainItem.selectedConference.core.subject : ""
font { font {
pixelSize: 20 * DefaultStyle.dp pixelSize: 20 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp weight: 800 * DefaultStyle.dp
@ -261,13 +328,20 @@ AbstractMainPage {
} }
} }
onClicked: { onClicked: {
if (UtilsCpp.isMe(mainItem.selectedConference.core.organizerAddress)) cancelAndDeleteConfDialog.cancel = UtilsCpp.isMe(mainItem.selectedConference.core.organizerAddress)
mainItem.selectedConference.core.lDeleteConferenceInfo() cancelAndDeleteConfDialog.open()
else
UtilsCpp.showInformationPopup(qsTr("Erreur"), qsTr("Vous pouvez supprimer une conférence seulement si vous en êtes l'organisateur"), false)
// mainItem.contactDeletionRequested(mainItem.selectedConference) // mainItem.contactDeletionRequested(mainItem.selectedConference)
deletePopup.close() deletePopup.close()
} }
Connections {
target: cancelAndDeleteConfDialog
onCancelRequested: {
mainItem.selectedConference.core.lCancelConferenceInfo()
}
onAccepted: {
mainItem.selectedConference.core.lDeleteConferenceInfo()
}
}
} }
} }
} }
@ -287,7 +361,7 @@ AbstractMainPage {
} }
Button { Button {
Layout.fillWidth: true Layout.fillWidth: true
text: mainItem.selectedConference && mainItem.selectedConference.core.uri text: mainItem.selectedConference ? mainItem.selectedConference.core.uri : ""
textSize: 14 * DefaultStyle.dp textSize: 14 * DefaultStyle.dp
textWeight: 400 * DefaultStyle.dp textWeight: 400 * DefaultStyle.dp
underline: true underline: true
@ -334,7 +408,7 @@ AbstractMainPage {
source: AppIcons.globe source: AppIcons.globe
} }
Text { Text {
text: qsTr("Time zone: ") + (mainItem.selectedConference && (mainItem.selectedConference.core.timeZoneModel.displayName + ", " + mainItem.selectedConference.core.timeZoneModel.countryName)) text: qsTr("Time zone: ") + (mainItem.selectedConference ? (mainItem.selectedConference.core.timeZoneModel.displayName + ", " + mainItem.selectedConference.core.timeZoneModel.countryName) : "")
font { font {
pixelSize: 14 * DefaultStyle.dp pixelSize: 14 * DefaultStyle.dp
capitalization: Font.Capitalize capitalization: Font.Capitalize
@ -354,7 +428,7 @@ AbstractMainPage {
colorizationColor: DefaultStyle.main2_600 colorizationColor: DefaultStyle.main2_600
} }
Text { Text {
text: mainItem.selectedConference && mainItem.selectedConference.core.description text: mainItem.selectedConference ? mainItem.selectedConference.core.description : ""
Layout.fillWidth: true Layout.fillWidth: true
font { font {
pixelSize: 14 * DefaultStyle.dp pixelSize: 14 * DefaultStyle.dp
@ -375,10 +449,10 @@ AbstractMainPage {
Avatar { Avatar {
Layout.preferredWidth: 45 * DefaultStyle.dp Layout.preferredWidth: 45 * DefaultStyle.dp
Layout.preferredHeight: 45 * DefaultStyle.dp Layout.preferredHeight: 45 * DefaultStyle.dp
address: mainItem.selectedConference && mainItem.selectedConference.core.organizerAddress address: mainItem.selectedConference ? mainItem.selectedConference.core.organizerAddress : ""
} }
Text { Text {
text: mainItem.selectedConference && mainItem.selectedConference.core.organizerName text: mainItem.selectedConference ? mainItem.selectedConference.core.organizerName : ""
font { font {
pixelSize: 14 * DefaultStyle.dp pixelSize: 14 * DefaultStyle.dp
capitalization: Font.Capitalize capitalization: Font.Capitalize
@ -402,7 +476,7 @@ AbstractMainPage {
id: participantList id: participantList
Layout.preferredHeight: Math.min(184 * DefaultStyle.dp, contentHeight) Layout.preferredHeight: Math.min(184 * DefaultStyle.dp, contentHeight)
Layout.fillWidth: true Layout.fillWidth: true
model: mainItem.selectedConference && mainItem.selectedConference.core.participants || [] model: mainItem.selectedConference ? mainItem.selectedConference.core.participants : []
clip: true clip: true
delegate: RowLayout { delegate: RowLayout {
height: 56 * DefaultStyle.dp height: 56 * DefaultStyle.dp
@ -434,7 +508,6 @@ AbstractMainPage {
} }
} }
Button { Button {
property var callObj
Layout.fillWidth: true Layout.fillWidth: true
text: qsTr("Rejoindre la réunion") text: qsTr("Rejoindre la réunion")
topPadding: 11 * DefaultStyle.dp topPadding: 11 * DefaultStyle.dp
@ -442,7 +515,7 @@ AbstractMainPage {
onClicked: { onClicked: {
console.log("TODO: join conf", mainItem.selectedConference.core.subject) console.log("TODO: join conf", mainItem.selectedConference.core.subject)
console.log(mainItem.selectedConference.core.uri) console.log(mainItem.selectedConference.core.uri)
callObj = UtilsCpp.createCall(mainItem.selectedConference.core.uri) UtilsCpp.setupConference(mainItem.selectedConference)
} }
} }
} }

View file

@ -24,17 +24,17 @@ QtObject {
property string chiffrement: "image://internal/chiffrement.svg" property string chiffrement: "image://internal/chiffrement.svg"
property string interoperable: "image://internal/interoperable.svg" property string interoperable: "image://internal/interoperable.svg"
property string phone: "image://internal/phone.svg" property string phone: "image://internal/phone.svg"
property string phoneSelected: "image://internal/phone-selected.svg" property string phoneSelected: "image://internal/phone-fill.svg"
property string newCall: "image://internal/phone-plus.svg" property string newCall: "image://internal/phone-plus.svg"
property string endCall: "image://internal/phone-disconnect.svg" property string endCall: "image://internal/phone-disconnect.svg"
property string callList: "image://internal/phone-list.svg" property string callList: "image://internal/phone-list.svg"
property string transferCall: "image://internal/phone-transfer.svg" property string transferCall: "image://internal/phone-transfer.svg"
property string adressBook: "image://internal/address-book.svg" property string adressBook: "image://internal/address-book.svg"
property string adressBookSelected: "image://internal/address-book-selected.svg" property string adressBookSelected: "image://internal/address-book-fill.svg"
property string chatTeardropText: "image://internal/chat-teardrop-text.svg" property string chatTeardropText: "image://internal/chat-teardrop-text.svg"
property string chatTeardropTextSelected: "image://internal/chat-teardrop-text-selected.svg" property string chatTeardropTextSelected: "image://internal/chat-teardrop-text-fill.svg"
property string usersThree: "image://internal/users-three.svg" property string usersThree: "image://internal/users-three.svg"
property string usersThreeSelected: "image://internal/users-three-selected.svg" property string usersThreeSelected: "image://internal/users-three-fill.svg"
property string userPlus: "image://internal/user-plus.svg" property string userPlus: "image://internal/user-plus.svg"
property string noItemImage: "image://internal/noItemImage.svg" property string noItemImage: "image://internal/noItemImage.svg"
property string verticalDots: "image://internal/dots-three-vertical.svg" property string verticalDots: "image://internal/dots-three-vertical.svg"
@ -45,12 +45,9 @@ QtObject {
property string magnifier: "image://internal/magnifying-glass.svg" property string magnifier: "image://internal/magnifying-glass.svg"
property string backspaceFill: "image://internal/backspace-fill.svg" property string backspaceFill: "image://internal/backspace-fill.svg"
property string closeX: "image://internal/x.svg" property string closeX: "image://internal/x.svg"
property string incomingCall: "image://internal/incoming_call.svg" property string arrowDownLeft: "image://internal/arrow-down-left.svg"
property string incomingCallMissed: "image://internal/incoming_call_missed.svg" property string arrowUpRight: "image://internal/arrow-up-right.svg"
property string incomingCallRejected: "image://internal/incoming_call_rejected.svg" property string arrowElbow: "image://internal/arrow-elbow-left.svg"
property string outgoingCall: "image://internal/outgoing_call.svg"
property string outgoingCallMissed: "image://internal/outgoing_call_missed.svg"
property string outgoingCallRejected: "image://internal/outgoing_call_rejected.svg"
property string microphone: "image://internal/microphone.svg" property string microphone: "image://internal/microphone.svg"
property string microphoneSlash: "image://internal/microphone-slash.svg" property string microphoneSlash: "image://internal/microphone-slash.svg"
property string camera: "image://internal/camera.svg" property string camera: "image://internal/camera.svg"
@ -83,5 +80,6 @@ QtObject {
property string usersTwo: "image://internal/users.svg" property string usersTwo: "image://internal/users.svg"
property string globe: "image://internal/globe-hemisphere-west.svg" property string globe: "image://internal/globe-hemisphere-west.svg"
property string slide: "image://internal/slideshow.svg" property string slide: "image://internal/slideshow.svg"
property string busyIndicator: "image://internal/busy-indicator.svg"
property string meeting: "image://internal/reunion.svg"
} }