audio settings
video settings app settings in settings file
This commit is contained in:
parent
ac528fc05c
commit
fb4ee6b579
28 changed files with 902 additions and 359 deletions
|
|
@ -49,6 +49,7 @@
|
||||||
#include "core/phone-number/PhoneNumber.hpp"
|
#include "core/phone-number/PhoneNumber.hpp"
|
||||||
#include "core/phone-number/PhoneNumberProxy.hpp"
|
#include "core/phone-number/PhoneNumberProxy.hpp"
|
||||||
#include "core/search/MagicSearchProxy.hpp"
|
#include "core/search/MagicSearchProxy.hpp"
|
||||||
|
#include "core/setting/SettingsCore.hpp"
|
||||||
#include "core/singleapplication/singleapplication.h"
|
#include "core/singleapplication/singleapplication.h"
|
||||||
#include "core/variant/VariantList.hpp"
|
#include "core/variant/VariantList.hpp"
|
||||||
#include "model/object/VariantObject.hpp"
|
#include "model/object/VariantObject.hpp"
|
||||||
|
|
@ -67,6 +68,9 @@ App::App(int &argc, char *argv[])
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
App::~App() {
|
||||||
|
}
|
||||||
|
|
||||||
App *App::getInstance() {
|
App *App::getInstance() {
|
||||||
return dynamic_cast<App *>(QApplication::instance());
|
return dynamic_cast<App *>(QApplication::instance());
|
||||||
}
|
}
|
||||||
|
|
@ -81,8 +85,53 @@ Notifier *App::getNotifier() const {
|
||||||
void App::init() {
|
void App::init() {
|
||||||
// Core. Manage the logger so it must be instantiate at first.
|
// Core. Manage the logger so it must be instantiate at first.
|
||||||
auto coreModel = CoreModel::create("", mLinphoneThread);
|
auto coreModel = CoreModel::create("", mLinphoneThread);
|
||||||
connect(mLinphoneThread, &QThread::started, coreModel.get(), &CoreModel::start);
|
connect(
|
||||||
mFirstLaunch = mSettings.value("firstLaunch", 1).toInt();
|
mLinphoneThread, &QThread::started, coreModel.get(),
|
||||||
|
[this, coreModel]() mutable {
|
||||||
|
coreModel->start();
|
||||||
|
auto settings = Settings::create();
|
||||||
|
QMetaObject::invokeMethod(App::getInstance()->thread(), [this, settings]() mutable {
|
||||||
|
mSettings = settings;
|
||||||
|
settings.reset();
|
||||||
|
|
||||||
|
// QML
|
||||||
|
mEngine = new QQmlApplicationEngine(this);
|
||||||
|
// Provide `+custom` folders for custom components and `5.9` for old components.
|
||||||
|
QStringList selectors("custom");
|
||||||
|
const QVersionNumber &version = QLibraryInfo::version();
|
||||||
|
if (version.majorVersion() == 5 && version.minorVersion() == 9) selectors.push_back("5.9");
|
||||||
|
auto selector = new QQmlFileSelector(mEngine, mEngine);
|
||||||
|
selector->setExtraSelectors(selectors);
|
||||||
|
qInfo() << log().arg("Activated selectors:") << selector->selector()->allSelectors();
|
||||||
|
|
||||||
|
mEngine->addImportPath(":/");
|
||||||
|
mEngine->rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath());
|
||||||
|
initCppInterfaces();
|
||||||
|
mEngine->addImageProvider(ImageProvider::ProviderId, new ImageProvider());
|
||||||
|
mEngine->addImageProvider(AvatarProvider::ProviderId, new AvatarProvider());
|
||||||
|
|
||||||
|
// Enable notifications.
|
||||||
|
mNotifier = new Notifier(mEngine);
|
||||||
|
|
||||||
|
const QUrl url(u"qrc:/Linphone/view/App/Main.qml"_qs);
|
||||||
|
QObject::connect(
|
||||||
|
mEngine, &QQmlApplicationEngine::objectCreated, this,
|
||||||
|
[this, url](QObject *obj, const QUrl &objUrl) {
|
||||||
|
if (url == objUrl) {
|
||||||
|
if (!obj) {
|
||||||
|
qCritical() << log().arg("Main.qml couldn't be load. The app will exit");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
mMainWindow = qobject_cast<QQuickWindow *>(obj);
|
||||||
|
Q_ASSERT(mMainWindow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
mEngine->load(url);
|
||||||
|
});
|
||||||
|
coreModel.reset();
|
||||||
|
},
|
||||||
|
Qt::SingleShotConnection);
|
||||||
// Console Commands
|
// Console Commands
|
||||||
createCommandParser();
|
createCommandParser();
|
||||||
mParser->parse(this->arguments());
|
mParser->parse(this->arguments());
|
||||||
|
|
@ -102,40 +151,6 @@ void App::init() {
|
||||||
|
|
||||||
qInfo() << log().arg("Display server : %1").arg(platformName());
|
qInfo() << log().arg("Display server : %1").arg(platformName());
|
||||||
|
|
||||||
// QML
|
|
||||||
mEngine = new QQmlApplicationEngine(this);
|
|
||||||
// Provide `+custom` folders for custom components and `5.9` for old components.
|
|
||||||
QStringList selectors("custom");
|
|
||||||
const QVersionNumber &version = QLibraryInfo::version();
|
|
||||||
if (version.majorVersion() == 5 && version.minorVersion() == 9) selectors.push_back("5.9");
|
|
||||||
auto selector = new QQmlFileSelector(mEngine, mEngine);
|
|
||||||
selector->setExtraSelectors(selectors);
|
|
||||||
qInfo() << log().arg("Activated selectors:") << selector->selector()->allSelectors();
|
|
||||||
|
|
||||||
mEngine->addImportPath(":/");
|
|
||||||
mEngine->rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath());
|
|
||||||
initCppInterfaces();
|
|
||||||
mEngine->addImageProvider(ImageProvider::ProviderId, new ImageProvider());
|
|
||||||
mEngine->addImageProvider(AvatarProvider::ProviderId, new AvatarProvider());
|
|
||||||
|
|
||||||
// Enable notifications.
|
|
||||||
mNotifier = new Notifier(mEngine);
|
|
||||||
|
|
||||||
const QUrl url(u"qrc:/Linphone/view/App/Main.qml"_qs);
|
|
||||||
QObject::connect(
|
|
||||||
mEngine, &QQmlApplicationEngine::objectCreated, this,
|
|
||||||
[this, url](QObject *obj, const QUrl &objUrl) {
|
|
||||||
if (url == objUrl) {
|
|
||||||
if (!obj) {
|
|
||||||
qCritical() << log().arg("Main.qml couldn't be load. The app will exit");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
mMainWindow = qobject_cast<QQuickWindow *>(obj);
|
|
||||||
Q_ASSERT(mMainWindow);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Qt::QueuedConnection);
|
|
||||||
mEngine->load(url);
|
|
||||||
// mEngine->load(u"qrc:/Linphone/view/Prototype/CameraPrototype.qml"_qs);
|
// mEngine->load(u"qrc:/Linphone/view/Prototype/CameraPrototype.qml"_qs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,6 +167,10 @@ void App::initCppInterfaces() {
|
||||||
"EnumsToStringCpp", 1, 0, "EnumsToStringCpp",
|
"EnumsToStringCpp", 1, 0, "EnumsToStringCpp",
|
||||||
[](QQmlEngine *engine, QJSEngine *) -> QObject * { return new EnumsToString(engine); });
|
[](QQmlEngine *engine, QJSEngine *) -> QObject * { return new EnumsToString(engine); });
|
||||||
|
|
||||||
|
qmlRegisterSingletonType<Settings>(
|
||||||
|
"SettingsCpp", 1, 0, "SettingsCpp",
|
||||||
|
[this](QQmlEngine *engine, QJSEngine *) -> QObject * { return mSettings.get(); });
|
||||||
|
|
||||||
qmlRegisterType<PhoneNumberProxy>(Constants::MainQmlUri, 1, 0, "PhoneNumberProxy");
|
qmlRegisterType<PhoneNumberProxy>(Constants::MainQmlUri, 1, 0, "PhoneNumberProxy");
|
||||||
qmlRegisterType<VariantObject>(Constants::MainQmlUri, 1, 0, "VariantObject");
|
qmlRegisterType<VariantObject>(Constants::MainQmlUri, 1, 0, "VariantObject");
|
||||||
|
|
||||||
|
|
@ -180,6 +199,8 @@ void App::clean() {
|
||||||
mNotifier = nullptr;
|
mNotifier = nullptr;
|
||||||
delete mEngine;
|
delete mEngine;
|
||||||
mEngine = nullptr;
|
mEngine = nullptr;
|
||||||
|
mSettings.reset();
|
||||||
|
mSettings = nullptr;
|
||||||
mLinphoneThread->wait(250);
|
mLinphoneThread->wait(250);
|
||||||
qApp->processEvents(QEventLoop::AllEvents, 250);
|
qApp->processEvents(QEventLoop::AllEvents, 250);
|
||||||
mLinphoneThread->exit();
|
mLinphoneThread->exit();
|
||||||
|
|
@ -267,17 +288,6 @@ void App::closeCallsWindow() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::setFirstLaunch(bool first) {
|
|
||||||
if (mFirstLaunch != first) {
|
|
||||||
mFirstLaunch = first;
|
|
||||||
mSettings.setValue("firstLaunch", first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool App::getFirstLaunch() const {
|
|
||||||
return mFirstLaunch;
|
|
||||||
}
|
|
||||||
|
|
||||||
QQuickWindow *App::getMainWindow() {
|
QQuickWindow *App::getMainWindow() {
|
||||||
return mMainWindow;
|
return mMainWindow;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@
|
||||||
|
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
#include <QQmlApplicationEngine>
|
#include <QQmlApplicationEngine>
|
||||||
#include <QSettings>
|
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
#include "core/setting/SettingsCore.hpp"
|
||||||
#include "core/singleapplication/singleapplication.h"
|
#include "core/singleapplication/singleapplication.h"
|
||||||
#include "model/core/CoreModel.hpp"
|
#include "model/core/CoreModel.hpp"
|
||||||
#include "tool/AbstractObject.hpp"
|
#include "tool/AbstractObject.hpp"
|
||||||
|
|
@ -35,6 +35,7 @@ class QQuickWindow;
|
||||||
class App : public SingleApplication, public AbstractObject {
|
class App : public SingleApplication, public AbstractObject {
|
||||||
public:
|
public:
|
||||||
App(int &argc, char *argv[]);
|
App(int &argc, char *argv[]);
|
||||||
|
~App();
|
||||||
static App *getInstance();
|
static App *getInstance();
|
||||||
Notifier *getNotifier() const;
|
Notifier *getNotifier() const;
|
||||||
|
|
||||||
|
|
@ -94,9 +95,6 @@ public:
|
||||||
QQuickWindow *getCallsWindow(QVariant callGui);
|
QQuickWindow *getCallsWindow(QVariant callGui);
|
||||||
void closeCallsWindow();
|
void closeCallsWindow();
|
||||||
|
|
||||||
bool getFirstLaunch() const;
|
|
||||||
void setFirstLaunch(bool first);
|
|
||||||
|
|
||||||
QQuickWindow *getMainWindow();
|
QQuickWindow *getMainWindow();
|
||||||
|
|
||||||
QQmlApplicationEngine *mEngine = nullptr;
|
QQmlApplicationEngine *mEngine = nullptr;
|
||||||
|
|
@ -112,10 +110,7 @@ private:
|
||||||
Notifier *mNotifier = nullptr;
|
Notifier *mNotifier = nullptr;
|
||||||
QQuickWindow *mMainWindow = nullptr;
|
QQuickWindow *mMainWindow = nullptr;
|
||||||
QQuickWindow *mCallsWindow = nullptr;
|
QQuickWindow *mCallsWindow = nullptr;
|
||||||
QSettings mSettings;
|
QSharedPointer<Settings> mSettings;
|
||||||
bool mFirstLaunch = true;
|
|
||||||
// TODO : changer ce count lorsqu'on aura liste d'appels
|
|
||||||
int callsCount = 0;
|
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ list(APPEND _LINPHONEAPP_SOURCES
|
||||||
core/search/MagicSearchList.cpp
|
core/search/MagicSearchList.cpp
|
||||||
core/search/MagicSearchProxy.cpp
|
core/search/MagicSearchProxy.cpp
|
||||||
|
|
||||||
core/setting/Settings.cpp
|
core/setting/SettingsCore.cpp
|
||||||
|
|
||||||
core/proxy/ListProxy.cpp
|
core/proxy/ListProxy.cpp
|
||||||
core/proxy/Proxy.cpp
|
core/proxy/Proxy.cpp
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,13 @@
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(CallCore)
|
DEFINE_ABSTRACT_OBJECT(CallCore)
|
||||||
|
|
||||||
|
QVariant createDeviceVariant(const QString &id, const QString &name) {
|
||||||
|
QVariantMap map;
|
||||||
|
map.insert("id", id);
|
||||||
|
map.insert("name", name);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
QSharedPointer<CallCore> CallCore::create(const std::shared_ptr<linphone::Call> &call) {
|
QSharedPointer<CallCore> CallCore::create(const std::shared_ptr<linphone::Call> &call) {
|
||||||
auto sharedPointer = QSharedPointer<CallCore>(new CallCore(call), &QObject::deleteLater);
|
auto sharedPointer = QSharedPointer<CallCore>(new CallCore(call), &QObject::deleteLater);
|
||||||
sharedPointer->setSelf(sharedPointer);
|
sharedPointer->setSelf(sharedPointer);
|
||||||
|
|
@ -45,16 +52,15 @@ CallCore::CallCore(const std::shared_ptr<linphone::Call> &call) : QObject(nullpt
|
||||||
mMicrophoneMuted = call->getMicrophoneMuted();
|
mMicrophoneMuted = call->getMicrophoneMuted();
|
||||||
mSpeakerMuted = call->getSpeakerMuted();
|
mSpeakerMuted = call->getSpeakerMuted();
|
||||||
mCameraEnabled = call->cameraEnabled();
|
mCameraEnabled = call->cameraEnabled();
|
||||||
mDuration = call->getDuration();
|
|
||||||
mState = LinphoneEnums::fromLinphone(call->getState());
|
mState = LinphoneEnums::fromLinphone(call->getState());
|
||||||
mPeerAddress = Utils::coreStringToAppString(mCallModel->getRemoteAddress()->asStringUriOnly());
|
mPeerAddress = Utils::coreStringToAppString(call->getRemoteAddress()->asStringUriOnly());
|
||||||
mStatus = LinphoneEnums::fromLinphone(call->getCallLog()->getStatus());
|
mStatus = LinphoneEnums::fromLinphone(call->getCallLog()->getStatus());
|
||||||
mTransferState = LinphoneEnums::fromLinphone(call->getTransferState());
|
mTransferState = LinphoneEnums::fromLinphone(call->getTransferState());
|
||||||
auto token = Utils::coreStringToAppString(mCallModel->getAuthenticationToken());
|
auto token = Utils::coreStringToAppString(mCallModel->getAuthenticationToken());
|
||||||
auto localToken = mDir == LinphoneEnums::CallDir::Incoming ? token.left(2).toUpper() : token.right(2).toUpper();
|
auto localToken = mDir == LinphoneEnums::CallDir::Incoming ? token.left(2).toUpper() : token.right(2).toUpper();
|
||||||
auto remoteToken = mDir == LinphoneEnums::CallDir::Outgoing ? token.left(2).toUpper() : token.right(2).toUpper();
|
auto remoteToken = mDir == LinphoneEnums::CallDir::Outgoing ? token.left(2).toUpper() : token.right(2).toUpper();
|
||||||
mEncryption = LinphoneEnums::fromLinphone(call->getParams()->getMediaEncryption());
|
mEncryption = LinphoneEnums::fromLinphone(call->getParams()->getMediaEncryption());
|
||||||
auto tokenVerified = mCallModel->getAuthenticationTokenVerified();
|
auto tokenVerified = call->getAuthenticationTokenVerified();
|
||||||
mLocalSas = localToken;
|
mLocalSas = localToken;
|
||||||
mRemoteSas = remoteToken;
|
mRemoteSas = remoteToken;
|
||||||
mIsSecured = (mEncryption == LinphoneEnums::MediaEncryption::Zrtp && tokenVerified) ||
|
mIsSecured = (mEncryption == LinphoneEnums::MediaEncryption::Zrtp && tokenVerified) ||
|
||||||
|
|
@ -65,6 +71,19 @@ CallCore::CallCore(const std::shared_ptr<linphone::Call> &call) : QObject(nullpt
|
||||||
mRemoteVideoEnabled = call->getRemoteParams() && call->getRemoteParams()->videoEnabled();
|
mRemoteVideoEnabled = call->getRemoteParams() && call->getRemoteParams()->videoEnabled();
|
||||||
mRecording = call->getParams() && call->getParams()->isRecording();
|
mRecording = call->getParams() && call->getParams()->isRecording();
|
||||||
mRemoteRecording = call->getRemoteParams() && call->getRemoteParams()->isRecording();
|
mRemoteRecording = call->getRemoteParams() && call->getRemoteParams()->isRecording();
|
||||||
|
mSpeakerVolumeGain = mCallModel->getSpeakerVolumeGain();
|
||||||
|
// TODO : change this with settings value when settings done
|
||||||
|
if (mSpeakerVolumeGain < 0) {
|
||||||
|
call->setSpeakerVolumeGain(0.5);
|
||||||
|
mSpeakerVolumeGain = 0.5;
|
||||||
|
}
|
||||||
|
mMicrophoneVolumeGain = call->getMicrophoneVolumeGain();
|
||||||
|
// TODO : change this with settings value when settings done
|
||||||
|
if (mMicrophoneVolumeGain < 0) {
|
||||||
|
call->setMicrophoneVolumeGain(0.5);
|
||||||
|
mMicrophoneVolumeGain = 0.5;
|
||||||
|
}
|
||||||
|
mMicrophoneVolume = call->getRecordVolume();
|
||||||
mRecordable = mState == LinphoneEnums::CallState::StreamsRunning;
|
mRecordable = mState == LinphoneEnums::CallState::StreamsRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,6 +140,9 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
mCallModelConnection->makeConnectToModel(&CallModel::durationChanged, [this](int duration) {
|
mCallModelConnection->makeConnectToModel(&CallModel::durationChanged, [this](int duration) {
|
||||||
mCallModelConnection->invokeToCore([this, duration]() { setDuration(duration); });
|
mCallModelConnection->invokeToCore([this, duration]() { setDuration(duration); });
|
||||||
});
|
});
|
||||||
|
mCallModelConnection->makeConnectToModel(&CallModel::microphoneVolumeChanged, [this](float volume) {
|
||||||
|
mCallModelConnection->invokeToCore([this, volume]() { setMicrophoneVolume(volume); });
|
||||||
|
});
|
||||||
mCallModelConnection->makeConnectToModel(
|
mCallModelConnection->makeConnectToModel(
|
||||||
&CallModel::stateChanged, [this](linphone::Call::State state, const std::string &message) {
|
&CallModel::stateChanged, [this](linphone::Call::State state, const std::string &message) {
|
||||||
mCallModelConnection->invokeToCore([this, state, message]() {
|
mCallModelConnection->invokeToCore([this, state, message]() {
|
||||||
|
|
@ -179,6 +201,35 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
encryption == LinphoneEnums::MediaEncryption::Dtls);
|
encryption == LinphoneEnums::MediaEncryption::Dtls);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
mCallModelConnection->makeConnectToCore(&CallCore::lSetSpeakerVolumeGain, [this](float gain) {
|
||||||
|
mCallModelConnection->invokeToModel([this, gain]() { mCallModel->setSpeakerVolumeGain(gain); });
|
||||||
|
});
|
||||||
|
mCallModelConnection->makeConnectToModel(&CallModel::speakerVolumeGainChanged, [this](float gain) {
|
||||||
|
mCallModelConnection->invokeToCore([this, gain]() { setSpeakerVolumeGain(gain); });
|
||||||
|
});
|
||||||
|
mCallModelConnection->makeConnectToCore(&CallCore::lSetMicrophoneVolumeGain, [this](float gain) {
|
||||||
|
mCallModelConnection->invokeToModel([this, gain]() { mCallModel->setMicrophoneVolumeGain(gain); });
|
||||||
|
});
|
||||||
|
mCallModelConnection->makeConnectToModel(&CallModel::microphoneVolumeGainChanged, [this](float gain) {
|
||||||
|
mCallModelConnection->invokeToCore([this, gain]() { setMicrophoneVolumeGain(gain); });
|
||||||
|
});
|
||||||
|
mCallModelConnection->makeConnectToCore(&CallCore::lSetInputAudioDevice, [this](const QString &id) {
|
||||||
|
mCallModelConnection->invokeToModel([this, id]() {
|
||||||
|
if (auto device = ToolModel::findAudioDevice(id)) {
|
||||||
|
mCallModel->setInputAudioDevice(device);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
mCallModelConnection->makeConnectToModel(&CallModel::inputAudioDeviceChanged, [this](const std::string &id) {
|
||||||
|
mCallModelConnection->invokeToCore([this, id]() {});
|
||||||
|
});
|
||||||
|
mCallModelConnection->makeConnectToCore(&CallCore::lSetOutputAudioDevice, [this](const QString &id) {
|
||||||
|
mCallModelConnection->invokeToModel([this, id]() {
|
||||||
|
if (auto device = ToolModel::findAudioDevice(id)) {
|
||||||
|
mCallModel->setOutputAudioDevice(device);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
mCallModelConnection->makeConnectToCore(&CallCore::lAccept, [this](bool withVideo) {
|
mCallModelConnection->makeConnectToCore(&CallCore::lAccept, [this](bool withVideo) {
|
||||||
mCallModelConnection->invokeToModel([this, withVideo]() { mCallModel->accept(withVideo); });
|
mCallModelConnection->invokeToModel([this, withVideo]() { mCallModel->accept(withVideo); });
|
||||||
});
|
});
|
||||||
|
|
@ -383,6 +434,36 @@ void CallCore::setRecordable(bool recordable) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float CallCore::getSpeakerVolumeGain() const {
|
||||||
|
return mSpeakerVolumeGain;
|
||||||
|
}
|
||||||
|
void CallCore::setSpeakerVolumeGain(float gain) {
|
||||||
|
if (mSpeakerVolumeGain != gain) {
|
||||||
|
mSpeakerVolumeGain = gain;
|
||||||
|
emit speakerVolumeGainChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float CallCore::getMicrophoneVolume() const {
|
||||||
|
return mMicrophoneVolume;
|
||||||
|
}
|
||||||
|
void CallCore::setMicrophoneVolume(float vol) {
|
||||||
|
if (mMicrophoneVolume != vol) {
|
||||||
|
mMicrophoneVolume = vol;
|
||||||
|
emit microphoneVolumeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float CallCore::getMicrophoneVolumeGain() const {
|
||||||
|
return mMicrophoneVolumeGain;
|
||||||
|
}
|
||||||
|
void CallCore::setMicrophoneVolumeGain(float gain) {
|
||||||
|
if (mMicrophoneVolumeGain != gain) {
|
||||||
|
mMicrophoneVolumeGain = gain;
|
||||||
|
emit microphoneVolumeGainChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LinphoneEnums::CallState CallCore::getTransferState() const {
|
LinphoneEnums::CallState CallCore::getTransferState() const {
|
||||||
return mTransferState;
|
return mTransferState;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,11 @@ class CallCore : public QObject, public AbstractObject {
|
||||||
Q_PROPERTY(bool recording READ getRecording WRITE setRecording NOTIFY recordingChanged)
|
Q_PROPERTY(bool recording READ getRecording WRITE setRecording NOTIFY recordingChanged)
|
||||||
Q_PROPERTY(bool remoteRecording READ getRemoteRecording WRITE setRemoteRecording NOTIFY remoteRecordingChanged)
|
Q_PROPERTY(bool remoteRecording READ getRemoteRecording WRITE setRemoteRecording NOTIFY remoteRecordingChanged)
|
||||||
Q_PROPERTY(bool recordable READ getRecordable WRITE setRecordable NOTIFY recordableChanged)
|
Q_PROPERTY(bool recordable READ getRecordable WRITE setRecordable NOTIFY recordableChanged)
|
||||||
|
Q_PROPERTY(
|
||||||
|
float speakerVolumeGain READ getSpeakerVolumeGain WRITE setSpeakerVolumeGain NOTIFY speakerVolumeGainChanged)
|
||||||
|
Q_PROPERTY(float microphoneVolumeGain READ getMicrophoneVolumeGain WRITE setMicrophoneVolumeGain NOTIFY
|
||||||
|
microphoneVolumeGainChanged)
|
||||||
|
Q_PROPERTY(float microVolume READ getMicrophoneVolume WRITE setMicrophoneVolume NOTIFY microphoneVolumeChanged)
|
||||||
Q_PROPERTY(LinphoneEnums::CallState transferState READ getTransferState NOTIFY transferStateChanged)
|
Q_PROPERTY(LinphoneEnums::CallState transferState READ getTransferState NOTIFY transferStateChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -112,6 +117,18 @@ public:
|
||||||
bool getRecordable() const;
|
bool getRecordable() const;
|
||||||
void setRecordable(bool recordable);
|
void setRecordable(bool recordable);
|
||||||
|
|
||||||
|
float getSpeakerVolumeGain() const;
|
||||||
|
void setSpeakerVolumeGain(float gain);
|
||||||
|
|
||||||
|
float getMicrophoneVolumeGain() const;
|
||||||
|
void setMicrophoneVolumeGain(float gain);
|
||||||
|
|
||||||
|
float getMicrophoneVolume() const;
|
||||||
|
void setMicrophoneVolume(float vol);
|
||||||
|
|
||||||
|
QString getInputDeviceName() const;
|
||||||
|
void setInputDeviceName(const QString &id);
|
||||||
|
|
||||||
LinphoneEnums::CallState getTransferState() const;
|
LinphoneEnums::CallState getTransferState() const;
|
||||||
void setTransferState(LinphoneEnums::CallState state, const QString &message);
|
void setTransferState(LinphoneEnums::CallState state, const QString &message);
|
||||||
|
|
||||||
|
|
@ -135,6 +152,9 @@ signals:
|
||||||
void recordingChanged();
|
void recordingChanged();
|
||||||
void remoteRecordingChanged();
|
void remoteRecordingChanged();
|
||||||
void recordableChanged();
|
void recordableChanged();
|
||||||
|
void speakerVolumeGainChanged();
|
||||||
|
void microphoneVolumeChanged();
|
||||||
|
void microphoneVolumeGainChanged();
|
||||||
|
|
||||||
// Linphone commands
|
// Linphone commands
|
||||||
void lAccept(bool withVideo); // Accept an incoming call
|
void lAccept(bool withVideo); // Accept an incoming call
|
||||||
|
|
@ -149,6 +169,10 @@ signals:
|
||||||
void lStartRecording();
|
void lStartRecording();
|
||||||
void lStopRecording();
|
void lStopRecording();
|
||||||
void lVerifyAuthenticationToken(bool verified);
|
void lVerifyAuthenticationToken(bool verified);
|
||||||
|
void lSetSpeakerVolumeGain(float gain);
|
||||||
|
void lSetMicrophoneVolumeGain(float gain);
|
||||||
|
void lSetInputAudioDevice(const QString &id);
|
||||||
|
void lSetOutputAudioDevice(const QString &id);
|
||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
Q_INVOKABLE void acceptWithVideo();
|
Q_INVOKABLE void acceptWithVideo();
|
||||||
|
|
@ -189,6 +213,9 @@ private:
|
||||||
bool mRecordable = false;
|
bool mRecordable = false;
|
||||||
QString mLocalSas;
|
QString mLocalSas;
|
||||||
QString mRemoteSas;
|
QString mRemoteSas;
|
||||||
|
float mSpeakerVolumeGain;
|
||||||
|
float mMicrophoneVolume;
|
||||||
|
float mMicrophoneVolumeGain;
|
||||||
QSharedPointer<SafeConnection<CallCore, CallModel>> mCallModelConnection;
|
QSharedPointer<SafeConnection<CallCore, CallModel>> mCallModelConnection;
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Settings.hpp"
|
|
||||||
|
|
||||||
#include <QUrl>
|
|
||||||
|
|
||||||
#include "core/path/Paths.hpp"
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
Settings::Settings(QObject *parent) : QObject(parent) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Settings::~Settings() {
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Settings::getConfigPath(const QCommandLineParser &parser) {
|
|
||||||
QString filePath = parser.isSet("config") ? parser.value("config") : "";
|
|
||||||
QString configPath;
|
|
||||||
if (!QUrl(filePath).isRelative()) {
|
|
||||||
// configPath = FileDownloader::synchronousDownload(filePath,
|
|
||||||
// Utils::coreStringToAppString(Paths::getConfigDirPath(false)), true));
|
|
||||||
}
|
|
||||||
if (configPath == "") configPath = Paths::getConfigFilePath(filePath, false);
|
|
||||||
if (configPath == "" && !filePath.isEmpty()) configPath = Paths::getConfigFilePath("", false);
|
|
||||||
return configPath;
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
||||||
*
|
|
||||||
* This file is part of linphone-desktop
|
|
||||||
* (see https://www.linphone.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SETTINGS_H_
|
|
||||||
#define SETTINGS_H_
|
|
||||||
|
|
||||||
#include <QCommandLineParser>
|
|
||||||
#include <QObject>
|
|
||||||
#include <QVariantMap>
|
|
||||||
|
|
||||||
class Settings : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
Settings(QObject *parent = Q_NULLPTR);
|
|
||||||
virtual ~Settings();
|
|
||||||
|
|
||||||
QString getConfigPath(const QCommandLineParser &parser = QCommandLineParser());
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
111
Linphone/core/setting/SettingsCore.cpp
Normal file
111
Linphone/core/setting/SettingsCore.cpp
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-desktop
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SettingsCore.hpp"
|
||||||
|
#include "core/App.hpp"
|
||||||
|
#include "core/path/Paths.hpp"
|
||||||
|
#include "model/tool/ToolModel.hpp"
|
||||||
|
#include "tool/Utils.hpp"
|
||||||
|
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
DEFINE_ABSTRACT_OBJECT(Settings)
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
QSharedPointer<Settings> Settings::create() {
|
||||||
|
auto sharedPointer = QSharedPointer<Settings>(new Settings(), &QObject::deleteLater);
|
||||||
|
sharedPointer->setSelf(sharedPointer);
|
||||||
|
sharedPointer->moveToThread(App::getInstance()->thread());
|
||||||
|
return sharedPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::Settings(QObject *parent) : QObject(parent) {
|
||||||
|
mustBeInLinphoneThread(getClassName());
|
||||||
|
mSettingsModel = Utils::makeQObject_ptr<SettingsModel>();
|
||||||
|
auto core = CoreModel::getInstance()->getCore();
|
||||||
|
for (auto &device : core->getExtendedAudioDevices()) {
|
||||||
|
auto core = CoreModel::getInstance()->getCore();
|
||||||
|
if (device->hasCapability(linphone::AudioDevice::Capabilities::CapabilityRecord)) {
|
||||||
|
mInputAudioDevices.append(Utils::coreStringToAppString(device->getId()));
|
||||||
|
// mInputAudioDevices.append(createDeviceVariant(Utils::coreStringToAppString(device->getId()),
|
||||||
|
// Utils::coreStringToAppString(device->getDeviceName())));
|
||||||
|
}
|
||||||
|
if (device->hasCapability(linphone::AudioDevice::Capabilities::CapabilityPlay)) {
|
||||||
|
mOutputAudioDevices.append(Utils::coreStringToAppString(device->getId()));
|
||||||
|
// mOutputAudioDevices.append(createDeviceVariant(Utils::coreStringToAppString(device->getId()),
|
||||||
|
// Utils::coreStringToAppString(device->getDeviceName())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto &device : core->getVideoDevicesList()) {
|
||||||
|
mVideoDevices.append(Utils::coreStringToAppString(device));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::~Settings() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::setSelf(QSharedPointer<Settings> me) {
|
||||||
|
mustBeInLinphoneThread(getClassName());
|
||||||
|
mSettingsModelConnection = QSharedPointer<SafeConnection<Settings, SettingsModel>>(
|
||||||
|
new SafeConnection<Settings, SettingsModel>(me, mSettingsModel), &QObject::deleteLater);
|
||||||
|
mSettingsModelConnection->makeConnectToCore(&Settings::lSetVideoDevice, [this](const QString &id) {
|
||||||
|
mSettingsModelConnection->invokeToModel(
|
||||||
|
[this, id]() { mSettingsModel->setVideoDevice(Utils::appStringToCoreString(id)); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Settings::getConfigPath(const QCommandLineParser &parser) {
|
||||||
|
QString filePath = parser.isSet("config") ? parser.value("config") : "";
|
||||||
|
QString configPath;
|
||||||
|
if (!QUrl(filePath).isRelative()) {
|
||||||
|
// configPath = FileDownloader::synchronousDownload(filePath,
|
||||||
|
// Utils::coreStringToAppString(Paths::getConfigDirPath(false)), true));
|
||||||
|
}
|
||||||
|
if (configPath == "") configPath = Paths::getConfigFilePath(filePath, false);
|
||||||
|
if (configPath == "" && !filePath.isEmpty()) configPath = Paths::getConfigFilePath("", false);
|
||||||
|
return configPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList Settings::getInputAudioDevicesList() const {
|
||||||
|
return mInputAudioDevices;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList Settings::getOutputAudioDevicesList() const {
|
||||||
|
return mOutputAudioDevices;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList Settings::getVideoDevicesList() const {
|
||||||
|
return mVideoDevices;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Settings::getFirstLaunch() const {
|
||||||
|
auto val = mAppSettings.value("firstLaunch", 1).toInt();
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::setFirstLaunch(bool first) {
|
||||||
|
auto firstLaunch = getFirstLaunch();
|
||||||
|
if (firstLaunch != first) {
|
||||||
|
mAppSettings.setValue("firstLaunch", (int)first);
|
||||||
|
mAppSettings.sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
74
Linphone/core/setting/SettingsCore.hpp
Normal file
74
Linphone/core/setting/SettingsCore.hpp
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-desktop
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SETTINGS_H_
|
||||||
|
#define SETTINGS_H_
|
||||||
|
|
||||||
|
#include "model/setting/SettingsModel.hpp"
|
||||||
|
#include "tool/thread/SafeConnection.hpp"
|
||||||
|
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
class Settings : public QObject, public AbstractObject {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QStringList inputAudioDevicesList READ getInputAudioDevicesList NOTIFY inputAudioDeviceChanged)
|
||||||
|
Q_PROPERTY(QStringList outputAudioDevicesList READ getOutputAudioDevicesList NOTIFY outputAudioDeviceChanged)
|
||||||
|
Q_PROPERTY(QStringList videoDevicesList READ getVideoDevicesList NOTIFY videoDeviceChanged)
|
||||||
|
public:
|
||||||
|
static QSharedPointer<Settings> create();
|
||||||
|
Settings(QObject *parent = Q_NULLPTR);
|
||||||
|
virtual ~Settings();
|
||||||
|
|
||||||
|
void setSelf(QSharedPointer<Settings> me);
|
||||||
|
|
||||||
|
QString getConfigPath(const QCommandLineParser &parser = QCommandLineParser());
|
||||||
|
|
||||||
|
QStringList getInputAudioDevicesList() const;
|
||||||
|
|
||||||
|
QStringList getOutputAudioDevicesList() const;
|
||||||
|
|
||||||
|
QStringList getVideoDevicesList() const;
|
||||||
|
|
||||||
|
Q_INVOKABLE void setFirstLaunch(bool first);
|
||||||
|
Q_INVOKABLE bool getFirstLaunch() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void inputAudioDeviceChanged(const QString &id);
|
||||||
|
void outputAudioDeviceChanged(const QString &id);
|
||||||
|
void videoDeviceChanged();
|
||||||
|
|
||||||
|
void lSetInputAudioDevice(const QString &device);
|
||||||
|
void lSetOutputAudioDevice(const QString &device);
|
||||||
|
void lSetVideoDevice(const QString &device);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<SettingsModel> mSettingsModel;
|
||||||
|
QStringList mInputAudioDevices;
|
||||||
|
QStringList mOutputAudioDevices;
|
||||||
|
QStringList mVideoDevices;
|
||||||
|
QSettings mAppSettings;
|
||||||
|
QSharedPointer<SafeConnection<Settings, SettingsModel>> mSettingsModelConnection;
|
||||||
|
|
||||||
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
@ -35,6 +35,13 @@ CallModel::CallModel(const std::shared_ptr<linphone::Call> &call, QObject *paren
|
||||||
mDurationTimer.setSingleShot(false);
|
mDurationTimer.setSingleShot(false);
|
||||||
connect(&mDurationTimer, &QTimer::timeout, this, [this]() { this->durationChanged(mMonitor->getDuration()); });
|
connect(&mDurationTimer, &QTimer::timeout, this, [this]() { this->durationChanged(mMonitor->getDuration()); });
|
||||||
mDurationTimer.start();
|
mDurationTimer.start();
|
||||||
|
|
||||||
|
mMicroVolumeTimer.setInterval(50);
|
||||||
|
mMicroVolumeTimer.setSingleShot(false);
|
||||||
|
connect(&mMicroVolumeTimer, &QTimer::timeout, this,
|
||||||
|
[this]() { this->microphoneVolumeChanged(Utils::computeVu(mMonitor->getRecordVolume())); });
|
||||||
|
mMicroVolumeTimer.start();
|
||||||
|
|
||||||
connect(this, &CallModel::stateChanged, this, [this] {
|
connect(this, &CallModel::stateChanged, this, [this] {
|
||||||
auto state = mMonitor->getState();
|
auto state = mMonitor->getState();
|
||||||
if (state == linphone::Call::State::Paused) setPaused(true);
|
if (state == linphone::Call::State::Paused) setPaused(true);
|
||||||
|
|
@ -144,6 +151,54 @@ void CallModel::setRecordFile(const std::string &path) {
|
||||||
mMonitor->update(params);
|
mMonitor->update(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CallModel::setSpeakerVolumeGain(float gain) {
|
||||||
|
mMonitor->setSpeakerVolumeGain(gain);
|
||||||
|
emit speakerVolumeGainChanged(gain);
|
||||||
|
}
|
||||||
|
|
||||||
|
float CallModel::getSpeakerVolumeGain() const {
|
||||||
|
auto gain = mMonitor->getSpeakerVolumeGain();
|
||||||
|
if (gain < 0) gain = CoreModel::getInstance()->getCore()->getPlaybackGainDb();
|
||||||
|
return gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::setMicrophoneVolumeGain(float gain) {
|
||||||
|
mMonitor->setMicrophoneVolumeGain(gain);
|
||||||
|
emit microphoneVolumeGainChanged(gain);
|
||||||
|
}
|
||||||
|
|
||||||
|
float CallModel::getMicrophoneVolumeGain() const {
|
||||||
|
auto gain = mMonitor->getMicrophoneVolumeGain();
|
||||||
|
return gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CallModel::getMicrophoneVolume() const {
|
||||||
|
auto volume = mMonitor->getRecordVolume();
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::setInputAudioDevice(const std::shared_ptr<linphone::AudioDevice> &device) {
|
||||||
|
mMonitor->setInputAudioDevice(device);
|
||||||
|
std::string deviceName;
|
||||||
|
if (device) deviceName = device->getDeviceName();
|
||||||
|
emit inputAudioDeviceChanged(deviceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const linphone::AudioDevice> CallModel::getInputAudioDevice() const {
|
||||||
|
return mMonitor->getInputAudioDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::setOutputAudioDevice(const std::shared_ptr<linphone::AudioDevice> &device) {
|
||||||
|
mMonitor->setOutputAudioDevice(device);
|
||||||
|
std::string deviceName;
|
||||||
|
if (device) deviceName = device->getDeviceName();
|
||||||
|
emit outputAudioDeviceChanged(deviceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const linphone::AudioDevice> CallModel::getOutputAudioDevice() const {
|
||||||
|
return mMonitor->getOutputAudioDevice();
|
||||||
|
}
|
||||||
|
|
||||||
std::string CallModel::getRecordFile() const {
|
std::string CallModel::getRecordFile() const {
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
return mMonitor->getParams()->getRecordFile();
|
return mMonitor->getParams()->getRecordFile();
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,20 @@ public:
|
||||||
void startRecording();
|
void startRecording();
|
||||||
void stopRecording();
|
void stopRecording();
|
||||||
void setRecordFile(const std::string &path);
|
void setRecordFile(const std::string &path);
|
||||||
|
void setSpeakerVolumeGain(float gain);
|
||||||
|
void setMicrophoneVolumeGain(float gain);
|
||||||
|
void setInputAudioDevice(const std::shared_ptr<linphone::AudioDevice> &id);
|
||||||
|
std::shared_ptr<const linphone::AudioDevice> getInputAudioDevice() const;
|
||||||
|
void setOutputAudioDevice(const std::shared_ptr<linphone::AudioDevice> &id);
|
||||||
|
std::shared_ptr<const linphone::AudioDevice> getOutputAudioDevice() const;
|
||||||
|
|
||||||
void setPaused(bool paused);
|
void setPaused(bool paused);
|
||||||
void transferTo(const std::shared_ptr<linphone::Address> &address);
|
void transferTo(const std::shared_ptr<linphone::Address> &address);
|
||||||
void terminateAllCalls();
|
void terminateAllCalls();
|
||||||
|
|
||||||
|
float getMicrophoneVolumeGain() const;
|
||||||
|
float getMicrophoneVolume() const;
|
||||||
|
float getSpeakerVolumeGain() const;
|
||||||
std::string getRecordFile() const;
|
std::string getRecordFile() const;
|
||||||
std::shared_ptr<const linphone::Address> getRemoteAddress();
|
std::shared_ptr<const linphone::Address> getRemoteAddress();
|
||||||
bool getAuthenticationTokenVerified() const;
|
bool getAuthenticationTokenVerified() const;
|
||||||
|
|
@ -62,13 +71,19 @@ signals:
|
||||||
void speakerMutedChanged(bool isMuted);
|
void speakerMutedChanged(bool isMuted);
|
||||||
void cameraEnabledChanged(bool enabled);
|
void cameraEnabledChanged(bool enabled);
|
||||||
void durationChanged(int);
|
void durationChanged(int);
|
||||||
|
void microphoneVolumeChanged(float);
|
||||||
void pausedChanged(bool paused);
|
void pausedChanged(bool paused);
|
||||||
void remoteVideoEnabledChanged(bool remoteVideoEnabled);
|
void remoteVideoEnabledChanged(bool remoteVideoEnabled);
|
||||||
void recordingChanged(bool recording);
|
void recordingChanged(bool recording);
|
||||||
void authenticationTokenVerifiedChanged(bool verified);
|
void authenticationTokenVerifiedChanged(bool verified);
|
||||||
|
void speakerVolumeGainChanged(float volume);
|
||||||
|
void microphoneVolumeGainChanged(float volume);
|
||||||
|
void inputAudioDeviceChanged(const std::string &id);
|
||||||
|
void outputAudioDeviceChanged(const std::string &id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTimer mDurationTimer;
|
QTimer mDurationTimer;
|
||||||
|
QTimer mMicroVolumeTimer;
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SettingsModel.hpp"
|
#include "SettingsModel.hpp"
|
||||||
|
#include "model/core/CoreModel.hpp"
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(SettingsModel)
|
DEFINE_ABSTRACT_OBJECT(SettingsModel)
|
||||||
|
|
@ -41,3 +43,20 @@ std::string SettingsModel::getEntryFullName(const std::string §ion, const st
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
return isReadOnly(section, name) ? name + "/readonly" : name;
|
return isReadOnly(section, name) ? name + "/readonly" : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::list<std::string> SettingsModel::getVideoDevices() const {
|
||||||
|
auto core = CoreModel::getInstance()->getCore();
|
||||||
|
return core->getVideoDevicesList();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SettingsModel::getVideoDevice() {
|
||||||
|
return CoreModel::getInstance()->getCore()->getVideoDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsModel::setVideoDevice(const std::string &id) {
|
||||||
|
auto core = CoreModel::getInstance()->getCore();
|
||||||
|
if (core->getVideoDevice() != id) {
|
||||||
|
CoreModel::getInstance()->getCore()->setVideoDevice(id);
|
||||||
|
emit videoDeviceChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
class SettingsModel : public QObject, public AbstractObject {
|
class SettingsModel : public QObject, public AbstractObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SettingsModel(QObject *parent = Q_NULLPTR);
|
SettingsModel(QObject *parent = Q_NULLPTR);
|
||||||
virtual ~SettingsModel();
|
virtual ~SettingsModel();
|
||||||
|
|
@ -39,10 +40,17 @@ public:
|
||||||
getEntryFullName(const std::string §ion,
|
getEntryFullName(const std::string §ion,
|
||||||
const std::string &name) const; // Return the full name of the entry : 'name/readonly' or 'name'
|
const std::string &name) const; // Return the full name of the entry : 'name/readonly' or 'name'
|
||||||
|
|
||||||
|
std::list<std::string> getVideoDevices() const;
|
||||||
|
void setVideoDevice(const std::string &id);
|
||||||
|
std::string getVideoDevice();
|
||||||
|
|
||||||
static const std::string UiSection;
|
static const std::string UiSection;
|
||||||
|
|
||||||
std::shared_ptr<linphone::Config> mConfig;
|
std::shared_ptr<linphone::Config> mConfig;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void videoDeviceChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,18 @@ std::shared_ptr<linphone::FriendPhoneNumber> ToolModel::makeLinphoneNumber(const
|
||||||
return linphoneNumber;
|
return linphoneNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<linphone::AudioDevice> ToolModel::findAudioDevice(const QString &id) {
|
||||||
|
std::string devId = Utils::appStringToCoreString(id);
|
||||||
|
auto devices = CoreModel::getInstance()->getCore()->getExtendedAudioDevices();
|
||||||
|
auto audioDevice =
|
||||||
|
find_if(devices.cbegin(), devices.cend(),
|
||||||
|
[&](const std::shared_ptr<linphone::AudioDevice> &audioItem) { return audioItem->getId() == devId; });
|
||||||
|
if (audioDevice != devices.cend()) {
|
||||||
|
return *audioDevice;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
QString ToolModel::getDisplayName(const std::shared_ptr<const linphone::Address> &address) {
|
QString ToolModel::getDisplayName(const std::shared_ptr<const linphone::Address> &address) {
|
||||||
QString displayName;
|
QString displayName;
|
||||||
if (address) {
|
if (address) {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ public:
|
||||||
|
|
||||||
static std::shared_ptr<linphone::Address> interpretUrl(const QString &address);
|
static std::shared_ptr<linphone::Address> interpretUrl(const QString &address);
|
||||||
static std::shared_ptr<linphone::FriendPhoneNumber> makeLinphoneNumber(const QString &label, const QString &number);
|
static std::shared_ptr<linphone::FriendPhoneNumber> makeLinphoneNumber(const QString &label, const QString &number);
|
||||||
|
static std::shared_ptr<linphone::AudioDevice> findAudioDevice(const QString &id);
|
||||||
|
|
||||||
static QString getDisplayName(const std::shared_ptr<const linphone::Address> &address);
|
static QString getDisplayName(const std::shared_ptr<const linphone::Address> &address);
|
||||||
static QString getDisplayName(QString address);
|
static QString getDisplayName(QString address);
|
||||||
|
|
|
||||||
|
|
@ -120,14 +120,6 @@ VariantObject *Utils::createCall(const QString &sipAddress,
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::setFirstLaunch(bool first) {
|
|
||||||
App::getInstance()->setFirstLaunch(first);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Utils::getFirstLaunch() {
|
|
||||||
return App::getInstance()->getFirstLaunch();
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,6 @@ public:
|
||||||
bool withVideo = false,
|
bool withVideo = false,
|
||||||
const QString &prepareTransfertAddress = "",
|
const QString &prepareTransfertAddress = "",
|
||||||
const QHash<QString, QString> &headers = {});
|
const QHash<QString, QString> &headers = {});
|
||||||
Q_INVOKABLE static void setFirstLaunch(bool first);
|
|
||||||
Q_INVOKABLE static bool getFirstLaunch();
|
|
||||||
Q_INVOKABLE static void openCallsWindow(CallGui *call);
|
Q_INVOKABLE static void openCallsWindow(CallGui *call);
|
||||||
Q_INVOKABLE static QQuickWindow *getMainWindow();
|
Q_INVOKABLE static QQuickWindow *getMainWindow();
|
||||||
Q_INVOKABLE static QQuickWindow *getCallsWindow(CallGui *callGui);
|
Q_INVOKABLE static QQuickWindow *getCallsWindow(CallGui *callGui);
|
||||||
|
|
@ -98,6 +96,16 @@ public:
|
||||||
static std::shared_ptr<T> makeQObject_ptr(Args &&...args) {
|
static std::shared_ptr<T> makeQObject_ptr(Args &&...args) {
|
||||||
return std::shared_ptr<T>(new T(args...), [](T *obj) { obj->deleteLater(); });
|
return std::shared_ptr<T>(new T(args...), [](T *obj) { obj->deleteLater(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline float computeVu(float volume) {
|
||||||
|
constexpr float VuMin = -20.f;
|
||||||
|
constexpr float VuMax = 4.f;
|
||||||
|
|
||||||
|
if (volume < VuMin) return 0.f;
|
||||||
|
if (volume > VuMax) return 1.f;
|
||||||
|
|
||||||
|
return (volume - VuMin) / (VuMax - VuMin);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // UTILS_H_
|
#endif // UTILS_H_
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import QtQuick.Controls as Control
|
||||||
import Linphone
|
import Linphone
|
||||||
import EnumsToStringCpp 1.0
|
import EnumsToStringCpp 1.0
|
||||||
import UtilsCpp 1.0
|
import UtilsCpp 1.0
|
||||||
|
import SettingsCpp 1.0
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
id: mainWindow
|
id: mainWindow
|
||||||
|
|
@ -277,7 +278,8 @@ Window {
|
||||||
bottomPadding: 8 * DefaultStyle.dp
|
bottomPadding: 8 * DefaultStyle.dp
|
||||||
leftPadding: 10 * DefaultStyle.dp
|
leftPadding: 10 * DefaultStyle.dp
|
||||||
rightPadding: 10 * DefaultStyle.dp
|
rightPadding: 10 * DefaultStyle.dp
|
||||||
visible: mainWindow.call.core.isSecured
|
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
|
||||||
|
|
@ -482,198 +484,341 @@ Window {
|
||||||
weight: 800 * DefaultStyle.dp
|
weight: 800 * DefaultStyle.dp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
contentItem: Control.StackView {
|
Control.StackView {
|
||||||
id: rightPanelStack
|
id: rightPanelStack
|
||||||
}
|
width: parent.width
|
||||||
Component {
|
height: parent.height
|
||||||
id: contactsListPanel
|
initialItem: callsListPanel
|
||||||
CallContactsLists {
|
Component {
|
||||||
sideMargin: 10 * DefaultStyle.dp
|
id: contactsListPanel
|
||||||
topMargin: 15 * DefaultStyle.dp
|
CallContactsLists {
|
||||||
groupCallVisible: false
|
sideMargin: 10 * DefaultStyle.dp
|
||||||
searchBarColor: DefaultStyle.grey_0
|
topMargin: 15 * DefaultStyle.dp
|
||||||
searchBarBorderColor: DefaultStyle.grey_200
|
groupCallVisible: false
|
||||||
onCallButtonPressed: (address) => {
|
searchBarColor: DefaultStyle.grey_0
|
||||||
mainWindow.call.core.lTransferCall(address)
|
searchBarBorderColor: DefaultStyle.grey_200
|
||||||
|
onCallButtonPressed: (address) => {
|
||||||
|
mainWindow.call.core.lTransferCall(address)
|
||||||
|
}
|
||||||
|
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Transfert d'appel")
|
||||||
}
|
}
|
||||||
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Transfert d'appel")
|
|
||||||
}
|
}
|
||||||
}
|
Component {
|
||||||
Component {
|
id: dialerPanel
|
||||||
id: dialerPanel
|
ColumnLayout {
|
||||||
ColumnLayout {
|
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Dialer")
|
||||||
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Dialer")
|
Item {
|
||||||
Item {
|
Layout.fillWidth: true
|
||||||
Layout.fillWidth: true
|
Layout.fillHeight: true
|
||||||
Layout.fillHeight: true
|
}
|
||||||
}
|
SearchBar {
|
||||||
SearchBar {
|
id: dialerTextInput
|
||||||
id: dialerTextInput
|
Layout.fillWidth: true
|
||||||
Layout.fillWidth: true
|
Layout.leftMargin: 10 * DefaultStyle.dp
|
||||||
Layout.leftMargin: 10 * DefaultStyle.dp
|
Layout.rightMargin: 10 * DefaultStyle.dp
|
||||||
Layout.rightMargin: 10 * DefaultStyle.dp
|
magnifierVisible: false
|
||||||
magnifierVisible: false
|
color: DefaultStyle.grey_0
|
||||||
color: DefaultStyle.grey_0
|
borderColor: DefaultStyle.grey_200
|
||||||
borderColor: DefaultStyle.grey_200
|
placeholderText: ""
|
||||||
placeholderText: ""
|
numericPad: numPad
|
||||||
numericPad: numPad
|
numericPadButton.visible: false
|
||||||
numericPadButton.visible: false
|
}
|
||||||
}
|
Item {
|
||||||
Item {
|
Layout.fillWidth: true
|
||||||
Layout.fillWidth: true
|
Layout.preferredHeight: numPad.height
|
||||||
Layout.preferredHeight: numPad.height
|
Layout.topMargin: 10 * DefaultStyle.dp
|
||||||
Layout.topMargin: 10 * DefaultStyle.dp
|
property var callObj
|
||||||
property var callObj
|
NumericPad {
|
||||||
NumericPad {
|
id: numPad
|
||||||
id: numPad
|
width: parent.width
|
||||||
width: parent.width
|
visible: parent.visible
|
||||||
visible: parent.visible
|
closeButtonVisible: false
|
||||||
closeButtonVisible: false
|
onLaunchCall: {
|
||||||
onLaunchCall: {
|
callObj = UtilsCpp.createCall(dialerTextInput.text + "@sip.linphone.org")
|
||||||
callObj = UtilsCpp.createCall(dialerTextInput.text)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Component {
|
||||||
Component {
|
id: callsListPanel
|
||||||
id: callsListPanel
|
ColumnLayout {
|
||||||
Control.Control {
|
RoundedBackgroundControl {
|
||||||
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Liste d'appel")
|
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Liste d'appel")
|
||||||
// width: callList.width
|
Layout.fillWidth: true
|
||||||
// height: callList.height
|
// height: Math.min(callList.height + topPadding + bottomPadding, rightPanelStack.height)
|
||||||
// padding: 15 * DefaultStyle.dp
|
onHeightChanged: console.log("calls list height changed", height)
|
||||||
topPadding: 15 * DefaultStyle.dp
|
height: Math.min(callList.height + topPadding + bottomPadding, rightPanelStack.height)
|
||||||
bottomPadding: 15 * DefaultStyle.dp
|
|
||||||
leftPadding: 15 * DefaultStyle.dp
|
|
||||||
rightPadding: 15 * DefaultStyle.dp
|
|
||||||
|
|
||||||
background: Rectangle {
|
topPadding: 15 * DefaultStyle.dp
|
||||||
anchors.fill: parent
|
bottomPadding: 15 * DefaultStyle.dp
|
||||||
anchors.leftMargin: 10 * DefaultStyle.dp
|
leftPadding: 15 * DefaultStyle.dp
|
||||||
anchors.rightMargin: 10 * DefaultStyle.dp
|
rightPadding: 15 * DefaultStyle.dp
|
||||||
anchors.topMargin: 10 * DefaultStyle.dp
|
backgroundColor: DefaultStyle.main2_0
|
||||||
anchors.bottomMargin: 10 * DefaultStyle.dp
|
|
||||||
color: DefaultStyle.main2_0
|
|
||||||
radius: 15 * DefaultStyle.dp
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: ListView {
|
contentItem: ListView {
|
||||||
id: callList
|
id: callList
|
||||||
model: callsModel
|
model: callsModel
|
||||||
height: contentHeight
|
height: Math.min(contentHeight, rightPanelStack.height)
|
||||||
spacing: 15 * DefaultStyle.dp
|
spacing: 15 * DefaultStyle.dp
|
||||||
|
|
||||||
onCountChanged: forceLayout()
|
onCountChanged: forceLayout()
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
id: callDelegate
|
id: callDelegate
|
||||||
width: callList.width
|
width: callList.width
|
||||||
height: 45 * DefaultStyle.dp
|
height: 45 * DefaultStyle.dp
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: delegateContent
|
id: delegateContent
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: 10 * DefaultStyle.dp
|
anchors.leftMargin: 10 * DefaultStyle.dp
|
||||||
anchors.rightMargin: 10 * DefaultStyle.dp
|
anchors.rightMargin: 10 * DefaultStyle.dp
|
||||||
Avatar {
|
Avatar {
|
||||||
id: delegateAvatar
|
id: delegateAvatar
|
||||||
address: modelData.core.peerAddress
|
address: modelData.core.peerAddress
|
||||||
Layout.preferredWidth: 45 * DefaultStyle.dp
|
Layout.preferredWidth: 45 * DefaultStyle.dp
|
||||||
Layout.preferredHeight: 45 * DefaultStyle.dp
|
Layout.preferredHeight: 45 * DefaultStyle.dp
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id: delegateName
|
||||||
|
property var remoteAddress: UtilsCpp.getDisplayName(modelData.core.peerAddress)
|
||||||
|
text: remoteAddress ? remoteAddress.value : ""
|
||||||
|
Connections {
|
||||||
|
target: modelData.core
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id: callStateText
|
||||||
|
text: modelData.core.state === LinphoneEnums.CallState.Paused
|
||||||
|
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
|
||||||
|
? qsTr("Appel en pause") : qsTr("Appel en cours")
|
||||||
|
}
|
||||||
|
PopupButton {
|
||||||
|
id: listCallOptionsButton
|
||||||
|
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||||
|
Layout.preferredHeight: 24 * DefaultStyle.dp
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
|
||||||
|
popup.contentItem: ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
Control.Button {
|
||||||
|
background: Item {}
|
||||||
|
contentItem: RowLayout {
|
||||||
|
Image {
|
||||||
|
source: modelData.core.state === LinphoneEnums.CallState.Paused
|
||||||
|
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
|
||||||
|
? AppIcons.phone : AppIcons.pause
|
||||||
|
sourceSize.width: 32 * DefaultStyle.dp
|
||||||
|
sourceSize.height: 32 * DefaultStyle.dp
|
||||||
|
Layout.preferredWidth: 32 * DefaultStyle.dp
|
||||||
|
Layout.preferredHeight: 32 * DefaultStyle.dp
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: modelData.core.state === LinphoneEnums.CallState.Paused
|
||||||
|
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
|
||||||
|
? qsTr("Reprendre l'appel") : qsTr("Mettre en pause")
|
||||||
|
color: DefaultStyle.main2_500main
|
||||||
|
Layout.preferredWidth: metrics.width
|
||||||
|
}
|
||||||
|
TextMetrics {
|
||||||
|
id: metrics
|
||||||
|
text: qsTr("Reprendre l'appel")
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: modelData.core.lSetPaused(!modelData.core.paused)
|
||||||
|
}
|
||||||
|
Control.Button {
|
||||||
|
background: Item {}
|
||||||
|
contentItem: RowLayout {
|
||||||
|
EffectImage {
|
||||||
|
source: AppIcons.endCall
|
||||||
|
colorizationColor: DefaultStyle.danger_500main
|
||||||
|
width: 32 * DefaultStyle.dp
|
||||||
|
height: 32 * DefaultStyle.dp
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
color: DefaultStyle.danger_500main
|
||||||
|
text: qsTr("Terminer l'appel")
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: mainWindow.endCall(modelData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MouseArea{
|
||||||
|
// anchors.fill: delegateLayout
|
||||||
|
// onClicked: {
|
||||||
|
// callsModel.currentCall = modelData
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
Text {
|
}
|
||||||
id: delegateName
|
}
|
||||||
property var remoteAddress: UtilsCpp.getDisplayName(modelData.core.peerAddress)
|
Item {
|
||||||
text: remoteAddress ? remoteAddress.value : ""
|
Layout.fillHeight: true
|
||||||
Connections {
|
}
|
||||||
target: modelData.core
|
}
|
||||||
|
}
|
||||||
|
Component {
|
||||||
|
id: settingsPanel
|
||||||
|
ColumnLayout {
|
||||||
|
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 {
|
||||||
|
source: 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item {
|
ComboBox {
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredWidth: parent.width
|
||||||
|
model: SettingsCpp.outputAudioDevicesList
|
||||||
|
onCurrentTextChanged: {
|
||||||
|
mainWindow.call.core.lSetOutputAudioDevice(currentText)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Text {
|
Slider {
|
||||||
id: callStateText
|
id: speakerVolume
|
||||||
text: mainWindow.call.core.state === LinphoneEnums.CallState.Paused
|
Layout.fillWidth: true
|
||||||
|| mainWindow.call.core.state === LinphoneEnums.CallState.PausedByRemote
|
from: 0.0
|
||||||
? qsTr("Appel en pause") : qsTr("Appel en cours")
|
to: 1.0
|
||||||
|
value: mainWindow.call && mainWindow.call.core.speakerVolumeGain
|
||||||
|
onMoved: {
|
||||||
|
mainWindow.call.core.lSetSpeakerVolumeGain(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PopupButton {
|
RowLayout {
|
||||||
id: listCallOptionsButton
|
Layout.fillWidth: true
|
||||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
EffectImage {
|
||||||
Layout.preferredHeight: 24 * DefaultStyle.dp
|
source: AppIcons.microphone
|
||||||
Layout.alignment: Qt.AlignRight
|
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
|
||||||
|
|
||||||
popup.contentItem: ColumnLayout {
|
background: Rectangle {
|
||||||
spacing: 0
|
x: audioTestSlider.leftPadding
|
||||||
Button {
|
y: audioTestSlider.topPadding + audioTestSlider.availableHeight / 2 - height / 2
|
||||||
leftPadding: 0
|
implicitWidth: 200 * DefaultStyle.dp
|
||||||
topPadding: 5 * DefaultStyle.dp
|
implicitHeight: 10 * DefaultStyle.dp
|
||||||
bottomPadding: 5 * DefaultStyle.dp
|
width: audioTestSlider.availableWidth
|
||||||
background: Item {}
|
height: implicitHeight
|
||||||
contentItem: RowLayout {
|
radius: 2 * DefaultStyle.dp
|
||||||
Image {
|
color: "#D9D9D9"
|
||||||
source: modelData.core.paused
|
|
||||||
? AppIcons.phone : AppIcons.pause
|
Rectangle {
|
||||||
sourceSize.width: 32 * DefaultStyle.dp
|
width: audioTestSlider.visualPosition * parent.width
|
||||||
sourceSize.height: 32 * DefaultStyle.dp
|
height: parent.height
|
||||||
Layout.preferredWidth: 32 * DefaultStyle.dp
|
gradient: Gradient {
|
||||||
Layout.preferredHeight: 32 * DefaultStyle.dp
|
orientation: Gradient.Horizontal
|
||||||
fillMode: Image.PreserveAspectFit
|
GradientStop { position: 0.0; color: "#6FF88D" }
|
||||||
}
|
GradientStop { position: 1.0; color: "#00D916" }
|
||||||
Text {
|
|
||||||
text: modelData.core.paused
|
|
||||||
? qsTr("Reprendre l'appel") : qsTr("Mettre en pause")
|
|
||||||
color: DefaultStyle.main2_500main
|
|
||||||
Layout.preferredWidth: metrics.width
|
|
||||||
}
|
|
||||||
TextMetrics {
|
|
||||||
id: metrics
|
|
||||||
text: qsTr("Reprendre l'appel")
|
|
||||||
}
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onClicked: modelData.core.lSetPaused(!modelData.core.paused)
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
leftPadding: 0
|
|
||||||
topPadding: 5 * DefaultStyle.dp
|
|
||||||
bottomPadding: 5 * DefaultStyle.dp
|
|
||||||
background: Item {}
|
|
||||||
contentItem: RowLayout {
|
|
||||||
EffectImage {
|
|
||||||
source: AppIcons.endCall
|
|
||||||
colorizationColor: DefaultStyle.danger_500main
|
|
||||||
width: 32 * DefaultStyle.dp
|
|
||||||
height: 32 * DefaultStyle.dp
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
color: DefaultStyle.danger_500main
|
|
||||||
text: qsTr("Terminer l'appel")
|
|
||||||
}
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onClicked: {
|
|
||||||
mainWindow.endCall(modelData)
|
|
||||||
mainWindow.callTerminatedByUser = true
|
|
||||||
}
|
}
|
||||||
|
radius: 2 * DefaultStyle.dp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
handle: Item {visible: false}
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
EffectImage {
|
||||||
|
source: 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// MouseArea{
|
Item {
|
||||||
// anchors.fill: delegateLayout
|
Layout.fillHeight: true
|
||||||
// onClicked: {
|
|
||||||
// callsModel.currentCall = modelData
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -845,9 +990,7 @@ Window {
|
||||||
Button {
|
Button {
|
||||||
id: callListButton
|
id: callListButton
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
background: Item {
|
background: Item {}
|
||||||
visible: false
|
|
||||||
}
|
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
Image {
|
Image {
|
||||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||||
|
|
@ -868,9 +1011,7 @@ Window {
|
||||||
Button {
|
Button {
|
||||||
id: dialerButton
|
id: dialerButton
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
background: Item {
|
background: Item {}
|
||||||
visible: false
|
|
||||||
}
|
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
Image {
|
Image {
|
||||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||||
|
|
@ -893,9 +1034,7 @@ Window {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
enabled: mainWindow.call.core.recordable
|
enabled: mainWindow.call.core.recordable
|
||||||
checkable: true
|
checkable: true
|
||||||
background: Item {
|
background: Item {}
|
||||||
visible: false
|
|
||||||
}
|
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
EffectImage {
|
EffectImage {
|
||||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||||
|
|
@ -914,29 +1053,47 @@ Window {
|
||||||
mainWindow.call.core.recording ? mainWindow.call.core.lStopRecording() : mainWindow.call.core.lStartRecording()
|
mainWindow.call.core.recording ? mainWindow.call.core.lStopRecording() : mainWindow.call.core.lStartRecording()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Button {
|
Control.Button {
|
||||||
id: speakerButton
|
id: speakerButton
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
checkable: true
|
checkable: true
|
||||||
background: Item {
|
background: Item {}
|
||||||
visible: false
|
|
||||||
}
|
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
EffectImage {
|
EffectImage {
|
||||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||||
Layout.preferredHeight: 24 * DefaultStyle.dp
|
Layout.preferredHeight: 24 * DefaultStyle.dp
|
||||||
fillMode: Image.PreserveAspectFit
|
fillMode: Image.PreserveAspectFit
|
||||||
source: mainWindow.call.core.speakerMuted ? AppIcons.speakerSlash : AppIcons.speaker
|
source: AppIcons.recordFill
|
||||||
colorizationColor: mainWindow.call.core.speakerMuted ? DefaultStyle.danger_500main : undefined
|
colorizationColor: mainWindow.call.core.recording ? DefaultStyle.danger_500main : undefined
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: mainWindow.call.core.speakerMuted ? qsTr("Activer le son") : qsTr("Désactiver le son")
|
color: mainWindow.call.core.recording ? DefaultStyle.danger_500main : DefaultStyle.main2_600
|
||||||
color: mainWindow.call.core.speakerMuted ? DefaultStyle.danger_500main : DefaultStyle.main2_600
|
text: mainWindow.call.core.recording ? qsTr("Terminer l'enregistrement") : qsTr("Enregistrer l'appel")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
onClicked: {
|
onClicked: {
|
||||||
mainWindow.call.core.lSetSpeakerMuted(!mainWindow.call.core.speakerMuted)
|
mainWindow.call.core.recording ? mainWindow.call.core.lStopRecording() : mainWindow.call.core.lStartRecording()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Control.Button {
|
||||||
|
id: settingsButton
|
||||||
|
Layout.fillWidth: true
|
||||||
|
background: Item{}
|
||||||
|
contentItem: RowLayout {
|
||||||
|
Image {
|
||||||
|
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||||
|
Layout.preferredHeight: 24 * DefaultStyle.dp
|
||||||
|
source: AppIcons.settings
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: qsTr("Paramètres")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
rightPanel.visible = true
|
||||||
|
rightPanel.replace(settingsPanel)
|
||||||
|
moreOptionsButton.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import QtQuick.Layouts 1.3
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import Linphone
|
import Linphone
|
||||||
import UtilsCpp 1.0
|
import UtilsCpp 1.0
|
||||||
|
import SettingsCpp 1.0
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
id: mainWindow
|
id: mainWindow
|
||||||
|
|
@ -35,14 +36,14 @@ Window {
|
||||||
StackView {
|
StackView {
|
||||||
id: mainWindowStackView
|
id: mainWindowStackView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
initialItem: accountProxy.haveAccount ? mainPage : UtilsCpp.getFirstLaunch() ? welcomePage : loginPage
|
initialItem: accountProxy.haveAccount ? mainPage : SettingsCpp.getFirstLaunch() ? welcomePage : loginPage
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
id: welcomePage
|
id: welcomePage
|
||||||
WelcomePage {
|
WelcomePage {
|
||||||
onStartButtonPressed: {
|
onStartButtonPressed: {
|
||||||
mainWindowStackView.replace(loginPage)// Replacing the first item will destroy the old.
|
mainWindowStackView.replace(loginPage)// Replacing the first item will destroy the old.
|
||||||
UtilsCpp.setFirstLaunch(false)
|
SettingsCpp.setFirstLaunch(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
||||||
view/Item/RectangleTest.qml
|
view/Item/RectangleTest.qml
|
||||||
view/Item/RoundedBackgroundControl.qml
|
view/Item/RoundedBackgroundControl.qml
|
||||||
view/Item/SearchBar.qml
|
view/Item/SearchBar.qml
|
||||||
|
view/Item/Slider.qml
|
||||||
view/Item/TabBar.qml
|
view/Item/TabBar.qml
|
||||||
view/Item/Text.qml
|
view/Item/Text.qml
|
||||||
view/Item/TextInput.qml
|
view/Item/TextInput.qml
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ ColumnLayout {
|
||||||
radius: 30 * DefaultStyle.dp
|
radius: 30 * DefaultStyle.dp
|
||||||
color: DefaultStyle.main1_500_main
|
color: DefaultStyle.main1_500_main
|
||||||
z: 1
|
z: 1
|
||||||
x: carouselButton.itemAt(mainItem.currentIndex).x
|
x: mainItem.currentIndex >= 0 && carouselButton.itemAt(mainItem.currentIndex) ? carouselButton.itemAt(mainItem.currentIndex).x : 0
|
||||||
Behavior on x { NumberAnimation {duration: 100}}
|
Behavior on x { NumberAnimation {duration: 100}}
|
||||||
}
|
}
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ ColumnLayout {
|
||||||
// Usage : each item of the model list must be {text: ..., img: ...}
|
// Usage : each item of the model list must be {text: ..., img: ...}
|
||||||
// If string list, only text part of the delegate will be filled
|
// If string list, only text part of the delegate will be filled
|
||||||
property var model: []
|
property var model: []
|
||||||
|
property alias combobox: combobox
|
||||||
readonly property string currentText: selectedItemText.text
|
readonly property string currentText: selectedItemText.text
|
||||||
property bool enableBackgroundColors: true
|
property bool enableBackgroundColors: true
|
||||||
readonly property bool hasActiveFocus: combobox.activeFocus
|
readonly property bool hasActiveFocus: combobox.activeFocus
|
||||||
|
|
@ -54,6 +55,7 @@ ColumnLayout {
|
||||||
id: selectedItemText
|
id: selectedItemText
|
||||||
color: combobox.enabled ? DefaultStyle.main2_600 : DefaultStyle.grey_400
|
color: combobox.enabled ? DefaultStyle.main2_600 : DefaultStyle.grey_400
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 1
|
||||||
font {
|
font {
|
||||||
pixelSize: 14 * DefaultStyle.dp
|
pixelSize: 14 * DefaultStyle.dp
|
||||||
weight: 400 * DefaultStyle.dp
|
weight: 400 * DefaultStyle.dp
|
||||||
|
|
@ -67,13 +69,13 @@ ColumnLayout {
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
var index = combobox.currentIndex < 0 ? 0 : combobox.currentIndex
|
var index = combobox.currentIndex < 0 ? 0 : combobox.currentIndex
|
||||||
if (mainItem.model[index].img) {
|
if (mainItem.model[index] && mainItem.model[index].img) {
|
||||||
selectedItemImg.source = mainItem.model[0].img
|
selectedItemImg.source = mainItem.model[index].img
|
||||||
}
|
}
|
||||||
if (mainItem.model[index].text)
|
if (mainItem.model[index] && mainItem.model[index].text)
|
||||||
selectedItemText.text = mainItem.model[0].text
|
selectedItemText.text = mainItem.model[index].text
|
||||||
else if (mainItem.model[index])
|
else if (mainItem.model[index])
|
||||||
selectedItemText.text = mainItem.model[0]
|
selectedItemText.text = mainItem.model[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,6 +134,7 @@ ColumnLayout {
|
||||||
? modelData
|
? modelData
|
||||||
: ""
|
: ""
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 1
|
||||||
font {
|
font {
|
||||||
pixelSize: 14 * DefaultStyle.dp
|
pixelSize: 14 * DefaultStyle.dp
|
||||||
weight: 400 * DefaultStyle.dp
|
weight: 400 * DefaultStyle.dp
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ Loader {
|
||||||
Image {
|
Image {
|
||||||
id: image
|
id: image
|
||||||
visible: !effect2.enabled
|
visible: !effect2.enabled
|
||||||
source: mainItem.source
|
source: mainItem.source ? mainItem.source : ""
|
||||||
fillMode: mainItem.fillMode
|
fillMode: mainItem.fillMode
|
||||||
sourceSize.width: width
|
sourceSize.width: width
|
||||||
sourceSize.height: height
|
sourceSize.height: height
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ MouseArea{
|
||||||
preventStealing: true
|
preventStealing: true
|
||||||
propagateComposedEvents: true
|
propagateComposedEvents: true
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onMScaleChanged: updateScale()
|
|
||||||
|
|
||||||
function updateScale(){// Avoid scaling if leading outside movableArea.
|
function updateScale(){// Avoid scaling if leading outside movableArea.
|
||||||
drag.target.height = Math.max(0, Math.min(movableArea.height, heightOrigin * mScale))
|
drag.target.height = Math.max(0, Math.min(movableArea.height, heightOrigin * mScale))
|
||||||
|
|
@ -42,6 +41,7 @@ MouseArea{
|
||||||
drag.target.x = Math.max(parentTLBounds.x + margin, Math.min(parentBRBounds.x - drag.target.width - margin, drag.target.x + x - margin))
|
drag.target.x = Math.max(parentTLBounds.x + margin, Math.min(parentBRBounds.x - drag.target.width - margin, drag.target.x + x - margin))
|
||||||
drag.target.y = Math.max(parentTLBounds.y + margin, Math.min(parentBRBounds.y - drag.target.height - margin, drag.target.y + y - margin))
|
drag.target.y = Math.max(parentTLBounds.y + margin, Math.min(parentBRBounds.y - drag.target.height - margin, drag.target.y + y - margin))
|
||||||
}
|
}
|
||||||
|
onMScaleChanged: updateScale()
|
||||||
onPositionChanged: (mouse) => {
|
onPositionChanged: (mouse) => {
|
||||||
if(dragging){
|
if(dragging){
|
||||||
updatePosition(mouse.x - xClicked, mouse.y - yClicked)
|
updatePosition(mouse.x - xClicked, mouse.y - yClicked)
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ ColumnLayout {
|
||||||
width: listView.width
|
width: listView.width
|
||||||
height: listView.height
|
height: listView.height
|
||||||
color: DefaultStyle.main2_300
|
color: DefaultStyle.main2_300
|
||||||
radius: 15 * DefaultStyle.dp
|
// radius: 15 * DefaultStyle.dp
|
||||||
y: listView.currentItem? listView.currentItem.y : 0
|
y: listView.currentItem? listView.currentItem.y : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ Button {
|
||||||
closePolicy: Popup.CloseOnPressOutsideParent |Popup.CloseOnPressOutside
|
closePolicy: Popup.CloseOnPressOutsideParent |Popup.CloseOnPressOutside
|
||||||
|
|
||||||
onAboutToShow: {
|
onAboutToShow: {
|
||||||
|
if (mainApplicationWindow == undefined) return;
|
||||||
var coord = mapToGlobal(mainItem.x, mainItem.y)
|
var coord = mapToGlobal(mainItem.x, mainItem.y)
|
||||||
if (coord.y + popup.height >= mainApplicationWindow.height) {
|
if (coord.y + popup.height >= mainApplicationWindow.height) {
|
||||||
y = -popup.height
|
y = -popup.height
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,17 @@ import QtQuick.Controls as Control
|
||||||
import Linphone
|
import Linphone
|
||||||
|
|
||||||
Control.Control {
|
Control.Control {
|
||||||
width: 360 * DefaultStyle.dp
|
id: mainItem
|
||||||
property color backgroundColor
|
// width: 360 * DefaultStyle.dp
|
||||||
topPadding: 10 * DefaultStyle.dp
|
property color backgroundColor: DefaultStyle.grey_0
|
||||||
bottomPadding: 10 * DefaultStyle.dp
|
padding: 10 * DefaultStyle.dp
|
||||||
leftPadding: 10 * DefaultStyle.dp
|
|
||||||
rightPadding: 10 * DefaultStyle.dp
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
// anchors.fill: parent
|
anchors.fill: parent
|
||||||
width: parent.width
|
|
||||||
height: parent.height
|
|
||||||
radius: 15 * DefaultStyle.dp
|
radius: 15 * DefaultStyle.dp
|
||||||
color: mainItem.backgroundColor ? mainItem.backgroundColor : DefaultStyle.grey_0
|
color: mainItem.backgroundColor
|
||||||
|
anchors.leftMargin: 10 * DefaultStyle.dp
|
||||||
|
anchors.rightMargin: 10 * DefaultStyle.dp
|
||||||
|
anchors.topMargin: 10 * DefaultStyle.dp
|
||||||
|
anchors.bottomMargin: 10 * DefaultStyle.dp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
53
Linphone/view/Item/Slider.qml
Normal file
53
Linphone/view/Item/Slider.qml
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls as Control
|
||||||
|
import Linphone
|
||||||
|
|
||||||
|
Control.Slider {
|
||||||
|
id: mainItem
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
x: mainItem.leftPadding
|
||||||
|
y: mainItem.topPadding + mainItem.availableHeight / 2 - height / 2
|
||||||
|
implicitWidth: 200 * DefaultStyle.dp
|
||||||
|
implicitHeight: 4 * DefaultStyle.dp
|
||||||
|
width: mainItem.availableWidth
|
||||||
|
height: implicitHeight
|
||||||
|
radius: 30 * DefaultStyle.dp
|
||||||
|
// TODO : change the colors when mockup indicates their names
|
||||||
|
color: "#D9D9D9"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: mainItem.visualPosition * parent.width
|
||||||
|
height: parent.height
|
||||||
|
gradient: Gradient {
|
||||||
|
orientation: Gradient.Horizontal
|
||||||
|
GradientStop { position: 0.0; color: "#FF9E79" }
|
||||||
|
GradientStop { position: 1.0; color: "#FE5E00" }
|
||||||
|
}
|
||||||
|
radius: 40 * DefaultStyle.dp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle: Item {
|
||||||
|
x: mainItem.leftPadding + mainItem.visualPosition * (mainItem.availableWidth - width)
|
||||||
|
y: mainItem.topPadding + mainItem.availableHeight / 2 - height / 2
|
||||||
|
implicitWidth: 16 * DefaultStyle.dp
|
||||||
|
implicitHeight: 16 * DefaultStyle.dp
|
||||||
|
Rectangle {
|
||||||
|
id: handleRect
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: 30 * DefaultStyle.dp
|
||||||
|
color: DefaultStyle.grey_0
|
||||||
|
}
|
||||||
|
MultiEffect {
|
||||||
|
source: handleRect
|
||||||
|
anchors.fill: handleRect
|
||||||
|
shadowEnabled: true
|
||||||
|
shadowColor: DefaultStyle.grey_1000
|
||||||
|
shadowBlur: 1
|
||||||
|
shadowOpacity: 0.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue