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/PhoneNumberProxy.hpp"
|
||||
#include "core/search/MagicSearchProxy.hpp"
|
||||
#include "core/setting/SettingsCore.hpp"
|
||||
#include "core/singleapplication/singleapplication.h"
|
||||
#include "core/variant/VariantList.hpp"
|
||||
#include "model/object/VariantObject.hpp"
|
||||
|
|
@ -67,6 +68,9 @@ App::App(int &argc, char *argv[])
|
|||
init();
|
||||
}
|
||||
|
||||
App::~App() {
|
||||
}
|
||||
|
||||
App *App::getInstance() {
|
||||
return dynamic_cast<App *>(QApplication::instance());
|
||||
}
|
||||
|
|
@ -81,8 +85,53 @@ Notifier *App::getNotifier() const {
|
|||
void App::init() {
|
||||
// Core. Manage the logger so it must be instantiate at first.
|
||||
auto coreModel = CoreModel::create("", mLinphoneThread);
|
||||
connect(mLinphoneThread, &QThread::started, coreModel.get(), &CoreModel::start);
|
||||
mFirstLaunch = mSettings.value("firstLaunch", 1).toInt();
|
||||
connect(
|
||||
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
|
||||
createCommandParser();
|
||||
mParser->parse(this->arguments());
|
||||
|
|
@ -102,40 +151,6 @@ void App::init() {
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -152,6 +167,10 @@ void App::initCppInterfaces() {
|
|||
"EnumsToStringCpp", 1, 0, "EnumsToStringCpp",
|
||||
[](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<VariantObject>(Constants::MainQmlUri, 1, 0, "VariantObject");
|
||||
|
||||
|
|
@ -180,6 +199,8 @@ void App::clean() {
|
|||
mNotifier = nullptr;
|
||||
delete mEngine;
|
||||
mEngine = nullptr;
|
||||
mSettings.reset();
|
||||
mSettings = nullptr;
|
||||
mLinphoneThread->wait(250);
|
||||
qApp->processEvents(QEventLoop::AllEvents, 250);
|
||||
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() {
|
||||
return mMainWindow;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@
|
|||
|
||||
#include <QCommandLineParser>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QSettings>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include "core/setting/SettingsCore.hpp"
|
||||
#include "core/singleapplication/singleapplication.h"
|
||||
#include "model/core/CoreModel.hpp"
|
||||
#include "tool/AbstractObject.hpp"
|
||||
|
|
@ -35,6 +35,7 @@ class QQuickWindow;
|
|||
class App : public SingleApplication, public AbstractObject {
|
||||
public:
|
||||
App(int &argc, char *argv[]);
|
||||
~App();
|
||||
static App *getInstance();
|
||||
Notifier *getNotifier() const;
|
||||
|
||||
|
|
@ -94,9 +95,6 @@ public:
|
|||
QQuickWindow *getCallsWindow(QVariant callGui);
|
||||
void closeCallsWindow();
|
||||
|
||||
bool getFirstLaunch() const;
|
||||
void setFirstLaunch(bool first);
|
||||
|
||||
QQuickWindow *getMainWindow();
|
||||
|
||||
QQmlApplicationEngine *mEngine = nullptr;
|
||||
|
|
@ -112,10 +110,7 @@ private:
|
|||
Notifier *mNotifier = nullptr;
|
||||
QQuickWindow *mMainWindow = nullptr;
|
||||
QQuickWindow *mCallsWindow = nullptr;
|
||||
QSettings mSettings;
|
||||
bool mFirstLaunch = true;
|
||||
// TODO : changer ce count lorsqu'on aura liste d'appels
|
||||
int callsCount = 0;
|
||||
QSharedPointer<Settings> mSettings;
|
||||
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ list(APPEND _LINPHONEAPP_SOURCES
|
|||
core/search/MagicSearchList.cpp
|
||||
core/search/MagicSearchProxy.cpp
|
||||
|
||||
core/setting/Settings.cpp
|
||||
core/setting/SettingsCore.cpp
|
||||
|
||||
core/proxy/ListProxy.cpp
|
||||
core/proxy/Proxy.cpp
|
||||
|
|
|
|||
|
|
@ -26,6 +26,13 @@
|
|||
|
||||
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) {
|
||||
auto sharedPointer = QSharedPointer<CallCore>(new CallCore(call), &QObject::deleteLater);
|
||||
sharedPointer->setSelf(sharedPointer);
|
||||
|
|
@ -45,16 +52,15 @@ CallCore::CallCore(const std::shared_ptr<linphone::Call> &call) : QObject(nullpt
|
|||
mMicrophoneMuted = call->getMicrophoneMuted();
|
||||
mSpeakerMuted = call->getSpeakerMuted();
|
||||
mCameraEnabled = call->cameraEnabled();
|
||||
mDuration = call->getDuration();
|
||||
mState = LinphoneEnums::fromLinphone(call->getState());
|
||||
mPeerAddress = Utils::coreStringToAppString(mCallModel->getRemoteAddress()->asStringUriOnly());
|
||||
mPeerAddress = Utils::coreStringToAppString(call->getRemoteAddress()->asStringUriOnly());
|
||||
mStatus = LinphoneEnums::fromLinphone(call->getCallLog()->getStatus());
|
||||
mTransferState = LinphoneEnums::fromLinphone(call->getTransferState());
|
||||
auto token = Utils::coreStringToAppString(mCallModel->getAuthenticationToken());
|
||||
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();
|
||||
mEncryption = LinphoneEnums::fromLinphone(call->getParams()->getMediaEncryption());
|
||||
auto tokenVerified = mCallModel->getAuthenticationTokenVerified();
|
||||
auto tokenVerified = call->getAuthenticationTokenVerified();
|
||||
mLocalSas = localToken;
|
||||
mRemoteSas = remoteToken;
|
||||
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();
|
||||
mRecording = call->getParams() && call->getParams()->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;
|
||||
}
|
||||
|
||||
|
|
@ -121,6 +140,9 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
|||
mCallModelConnection->makeConnectToModel(&CallModel::durationChanged, [this](int duration) {
|
||||
mCallModelConnection->invokeToCore([this, duration]() { setDuration(duration); });
|
||||
});
|
||||
mCallModelConnection->makeConnectToModel(&CallModel::microphoneVolumeChanged, [this](float volume) {
|
||||
mCallModelConnection->invokeToCore([this, volume]() { setMicrophoneVolume(volume); });
|
||||
});
|
||||
mCallModelConnection->makeConnectToModel(
|
||||
&CallModel::stateChanged, [this](linphone::Call::State state, const std::string &message) {
|
||||
mCallModelConnection->invokeToCore([this, state, message]() {
|
||||
|
|
@ -179,6 +201,35 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
|||
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->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 {
|
||||
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 remoteRecording READ getRemoteRecording WRITE setRemoteRecording NOTIFY remoteRecordingChanged)
|
||||
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)
|
||||
|
||||
public:
|
||||
|
|
@ -112,6 +117,18 @@ public:
|
|||
bool getRecordable() const;
|
||||
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;
|
||||
void setTransferState(LinphoneEnums::CallState state, const QString &message);
|
||||
|
||||
|
|
@ -135,6 +152,9 @@ signals:
|
|||
void recordingChanged();
|
||||
void remoteRecordingChanged();
|
||||
void recordableChanged();
|
||||
void speakerVolumeGainChanged();
|
||||
void microphoneVolumeChanged();
|
||||
void microphoneVolumeGainChanged();
|
||||
|
||||
// Linphone commands
|
||||
void lAccept(bool withVideo); // Accept an incoming call
|
||||
|
|
@ -149,6 +169,10 @@ signals:
|
|||
void lStartRecording();
|
||||
void lStopRecording();
|
||||
void lVerifyAuthenticationToken(bool verified);
|
||||
void lSetSpeakerVolumeGain(float gain);
|
||||
void lSetMicrophoneVolumeGain(float gain);
|
||||
void lSetInputAudioDevice(const QString &id);
|
||||
void lSetOutputAudioDevice(const QString &id);
|
||||
|
||||
/* TODO
|
||||
Q_INVOKABLE void acceptWithVideo();
|
||||
|
|
@ -189,6 +213,9 @@ private:
|
|||
bool mRecordable = false;
|
||||
QString mLocalSas;
|
||||
QString mRemoteSas;
|
||||
float mSpeakerVolumeGain;
|
||||
float mMicrophoneVolume;
|
||||
float mMicrophoneVolumeGain;
|
||||
QSharedPointer<SafeConnection<CallCore, CallModel>> mCallModelConnection;
|
||||
|
||||
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);
|
||||
connect(&mDurationTimer, &QTimer::timeout, this, [this]() { this->durationChanged(mMonitor->getDuration()); });
|
||||
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] {
|
||||
auto state = mMonitor->getState();
|
||||
if (state == linphone::Call::State::Paused) setPaused(true);
|
||||
|
|
@ -144,6 +151,54 @@ void CallModel::setRecordFile(const std::string &path) {
|
|||
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 {
|
||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||
return mMonitor->getParams()->getRecordFile();
|
||||
|
|
|
|||
|
|
@ -46,11 +46,20 @@ public:
|
|||
void startRecording();
|
||||
void stopRecording();
|
||||
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 transferTo(const std::shared_ptr<linphone::Address> &address);
|
||||
void terminateAllCalls();
|
||||
|
||||
float getMicrophoneVolumeGain() const;
|
||||
float getMicrophoneVolume() const;
|
||||
float getSpeakerVolumeGain() const;
|
||||
std::string getRecordFile() const;
|
||||
std::shared_ptr<const linphone::Address> getRemoteAddress();
|
||||
bool getAuthenticationTokenVerified() const;
|
||||
|
|
@ -62,13 +71,19 @@ signals:
|
|||
void speakerMutedChanged(bool isMuted);
|
||||
void cameraEnabledChanged(bool enabled);
|
||||
void durationChanged(int);
|
||||
void microphoneVolumeChanged(float);
|
||||
void pausedChanged(bool paused);
|
||||
void remoteVideoEnabledChanged(bool remoteVideoEnabled);
|
||||
void recordingChanged(bool recording);
|
||||
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:
|
||||
QTimer mDurationTimer;
|
||||
QTimer mMicroVolumeTimer;
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
|
||||
#include "SettingsModel.hpp"
|
||||
#include "model/core/CoreModel.hpp"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(SettingsModel)
|
||||
|
|
@ -41,3 +43,20 @@ std::string SettingsModel::getEntryFullName(const std::string §ion, const st
|
|||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||
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 {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SettingsModel(QObject *parent = Q_NULLPTR);
|
||||
virtual ~SettingsModel();
|
||||
|
|
@ -39,10 +40,17 @@ public:
|
|||
getEntryFullName(const std::string §ion,
|
||||
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;
|
||||
|
||||
std::shared_ptr<linphone::Config> mConfig;
|
||||
|
||||
signals:
|
||||
void videoDeviceChanged();
|
||||
|
||||
private:
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
|
|
|
|||
|
|
@ -56,6 +56,18 @@ std::shared_ptr<linphone::FriendPhoneNumber> ToolModel::makeLinphoneNumber(const
|
|||
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 displayName;
|
||||
if (address) {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ public:
|
|||
|
||||
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::AudioDevice> findAudioDevice(const QString &id);
|
||||
|
||||
static QString getDisplayName(const std::shared_ptr<const linphone::Address> &address);
|
||||
static QString getDisplayName(QString address);
|
||||
|
|
|
|||
|
|
@ -120,14 +120,6 @@ VariantObject *Utils::createCall(const QString &sipAddress,
|
|||
return data;
|
||||
}
|
||||
|
||||
void Utils::setFirstLaunch(bool first) {
|
||||
App::getInstance()->setFirstLaunch(first);
|
||||
}
|
||||
|
||||
bool Utils::getFirstLaunch() {
|
||||
return App::getInstance()->getFirstLaunch();
|
||||
}
|
||||
|
||||
void Utils::openCallsWindow(CallGui *call) {
|
||||
if (call) App::getInstance()->getCallsWindow(QVariant::fromValue(call))->show();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,8 +60,6 @@ public:
|
|||
bool withVideo = false,
|
||||
const QString &prepareTransfertAddress = "",
|
||||
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 QQuickWindow *getMainWindow();
|
||||
Q_INVOKABLE static QQuickWindow *getCallsWindow(CallGui *callGui);
|
||||
|
|
@ -98,6 +96,16 @@ public:
|
|||
static std::shared_ptr<T> makeQObject_ptr(Args &&...args) {
|
||||
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_
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import QtQuick.Controls as Control
|
|||
import Linphone
|
||||
import EnumsToStringCpp 1.0
|
||||
import UtilsCpp 1.0
|
||||
import SettingsCpp 1.0
|
||||
|
||||
Window {
|
||||
id: mainWindow
|
||||
|
|
@ -277,7 +278,8 @@ Window {
|
|||
bottomPadding: 8 * DefaultStyle.dp
|
||||
leftPadding: 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 {
|
||||
anchors.fill: parent
|
||||
border.color: DefaultStyle.info_500_main
|
||||
|
|
@ -482,198 +484,341 @@ Window {
|
|||
weight: 800 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
contentItem: Control.StackView {
|
||||
Control.StackView {
|
||||
id: rightPanelStack
|
||||
}
|
||||
Component {
|
||||
id: contactsListPanel
|
||||
CallContactsLists {
|
||||
sideMargin: 10 * DefaultStyle.dp
|
||||
topMargin: 15 * DefaultStyle.dp
|
||||
groupCallVisible: false
|
||||
searchBarColor: DefaultStyle.grey_0
|
||||
searchBarBorderColor: DefaultStyle.grey_200
|
||||
onCallButtonPressed: (address) => {
|
||||
mainWindow.call.core.lTransferCall(address)
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
initialItem: callsListPanel
|
||||
Component {
|
||||
id: contactsListPanel
|
||||
CallContactsLists {
|
||||
sideMargin: 10 * DefaultStyle.dp
|
||||
topMargin: 15 * DefaultStyle.dp
|
||||
groupCallVisible: false
|
||||
searchBarColor: DefaultStyle.grey_0
|
||||
searchBarBorderColor: DefaultStyle.grey_200
|
||||
onCallButtonPressed: (address) => {
|
||||
mainWindow.call.core.lTransferCall(address)
|
||||
}
|
||||
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Transfert d'appel")
|
||||
}
|
||||
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Transfert d'appel")
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: dialerPanel
|
||||
ColumnLayout {
|
||||
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Dialer")
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
SearchBar {
|
||||
id: dialerTextInput
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 10 * DefaultStyle.dp
|
||||
Layout.rightMargin: 10 * DefaultStyle.dp
|
||||
magnifierVisible: false
|
||||
color: DefaultStyle.grey_0
|
||||
borderColor: DefaultStyle.grey_200
|
||||
placeholderText: ""
|
||||
numericPad: numPad
|
||||
numericPadButton.visible: false
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: numPad.height
|
||||
Layout.topMargin: 10 * DefaultStyle.dp
|
||||
property var callObj
|
||||
NumericPad {
|
||||
id: numPad
|
||||
width: parent.width
|
||||
visible: parent.visible
|
||||
closeButtonVisible: false
|
||||
onLaunchCall: {
|
||||
callObj = UtilsCpp.createCall(dialerTextInput.text)
|
||||
Component {
|
||||
id: dialerPanel
|
||||
ColumnLayout {
|
||||
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Dialer")
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
SearchBar {
|
||||
id: dialerTextInput
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 10 * DefaultStyle.dp
|
||||
Layout.rightMargin: 10 * DefaultStyle.dp
|
||||
magnifierVisible: false
|
||||
color: DefaultStyle.grey_0
|
||||
borderColor: DefaultStyle.grey_200
|
||||
placeholderText: ""
|
||||
numericPad: numPad
|
||||
numericPadButton.visible: false
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: numPad.height
|
||||
Layout.topMargin: 10 * DefaultStyle.dp
|
||||
property var callObj
|
||||
NumericPad {
|
||||
id: numPad
|
||||
width: parent.width
|
||||
visible: parent.visible
|
||||
closeButtonVisible: false
|
||||
onLaunchCall: {
|
||||
callObj = UtilsCpp.createCall(dialerTextInput.text + "@sip.linphone.org")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: callsListPanel
|
||||
Control.Control {
|
||||
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Liste d'appel")
|
||||
// width: callList.width
|
||||
// height: callList.height
|
||||
// padding: 15 * DefaultStyle.dp
|
||||
topPadding: 15 * DefaultStyle.dp
|
||||
bottomPadding: 15 * DefaultStyle.dp
|
||||
leftPadding: 15 * DefaultStyle.dp
|
||||
rightPadding: 15 * DefaultStyle.dp
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 10 * DefaultStyle.dp
|
||||
anchors.rightMargin: 10 * DefaultStyle.dp
|
||||
anchors.topMargin: 10 * DefaultStyle.dp
|
||||
anchors.bottomMargin: 10 * DefaultStyle.dp
|
||||
color: DefaultStyle.main2_0
|
||||
radius: 15 * DefaultStyle.dp
|
||||
}
|
||||
Component {
|
||||
id: callsListPanel
|
||||
ColumnLayout {
|
||||
RoundedBackgroundControl {
|
||||
Control.StackView.onActivated: rightPanelTitle.text = qsTr("Liste d'appel")
|
||||
Layout.fillWidth: true
|
||||
// height: Math.min(callList.height + topPadding + bottomPadding, rightPanelStack.height)
|
||||
onHeightChanged: console.log("calls list height changed", height)
|
||||
height: Math.min(callList.height + topPadding + bottomPadding, rightPanelStack.height)
|
||||
|
||||
contentItem: ListView {
|
||||
id: callList
|
||||
model: callsModel
|
||||
height: contentHeight
|
||||
spacing: 15 * DefaultStyle.dp
|
||||
topPadding: 15 * DefaultStyle.dp
|
||||
bottomPadding: 15 * DefaultStyle.dp
|
||||
leftPadding: 15 * DefaultStyle.dp
|
||||
rightPadding: 15 * DefaultStyle.dp
|
||||
backgroundColor: DefaultStyle.main2_0
|
||||
|
||||
contentItem: ListView {
|
||||
id: callList
|
||||
model: callsModel
|
||||
height: Math.min(contentHeight, rightPanelStack.height)
|
||||
spacing: 15 * DefaultStyle.dp
|
||||
|
||||
onCountChanged: forceLayout()
|
||||
onCountChanged: forceLayout()
|
||||
|
||||
delegate: Item {
|
||||
id: callDelegate
|
||||
width: callList.width
|
||||
height: 45 * DefaultStyle.dp
|
||||
delegate: Item {
|
||||
id: callDelegate
|
||||
width: callList.width
|
||||
height: 45 * DefaultStyle.dp
|
||||
|
||||
RowLayout {
|
||||
id: delegateContent
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 10 * DefaultStyle.dp
|
||||
anchors.rightMargin: 10 * DefaultStyle.dp
|
||||
Avatar {
|
||||
id: delegateAvatar
|
||||
address: modelData.core.peerAddress
|
||||
Layout.preferredWidth: 45 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 45 * DefaultStyle.dp
|
||||
RowLayout {
|
||||
id: delegateContent
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 10 * DefaultStyle.dp
|
||||
anchors.rightMargin: 10 * DefaultStyle.dp
|
||||
Avatar {
|
||||
id: delegateAvatar
|
||||
address: modelData.core.peerAddress
|
||||
Layout.preferredWidth: 45 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 45 * DefaultStyle.dp
|
||||
}
|
||||
Text {
|
||||
id: delegateName
|
||||
property var remoteAddress: UtilsCpp.getDisplayName(modelData.core.peerAddress)
|
||||
text: remoteAddress ? remoteAddress.value : ""
|
||||
Connections {
|
||||
target: modelData.core
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Text {
|
||||
id: callStateText
|
||||
text: modelData.core.state === LinphoneEnums.CallState.Paused
|
||||
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
|
||||
? qsTr("Appel en pause") : qsTr("Appel en cours")
|
||||
}
|
||||
PopupButton {
|
||||
id: listCallOptionsButton
|
||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 24 * DefaultStyle.dp
|
||||
Layout.alignment: Qt.AlignRight
|
||||
|
||||
popup.contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
Control.Button {
|
||||
background: Item {}
|
||||
contentItem: RowLayout {
|
||||
Image {
|
||||
source: modelData.core.state === LinphoneEnums.CallState.Paused
|
||||
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
|
||||
? AppIcons.phone : AppIcons.pause
|
||||
sourceSize.width: 32 * DefaultStyle.dp
|
||||
sourceSize.height: 32 * DefaultStyle.dp
|
||||
Layout.preferredWidth: 32 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 32 * DefaultStyle.dp
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
Text {
|
||||
text: modelData.core.state === LinphoneEnums.CallState.Paused
|
||||
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
|
||||
? qsTr("Reprendre l'appel") : qsTr("Mettre en pause")
|
||||
color: DefaultStyle.main2_500main
|
||||
Layout.preferredWidth: metrics.width
|
||||
}
|
||||
TextMetrics {
|
||||
id: metrics
|
||||
text: qsTr("Reprendre l'appel")
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
onClicked: modelData.core.lSetPaused(!modelData.core.paused)
|
||||
}
|
||||
Control.Button {
|
||||
background: Item {}
|
||||
contentItem: RowLayout {
|
||||
EffectImage {
|
||||
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)
|
||||
text: remoteAddress ? remoteAddress.value : ""
|
||||
Connections {
|
||||
target: modelData.core
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
}
|
||||
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 {
|
||||
Layout.fillHeight: true
|
||||
ComboBox {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: parent.width
|
||||
model: SettingsCpp.outputAudioDevicesList
|
||||
onCurrentTextChanged: {
|
||||
mainWindow.call.core.lSetOutputAudioDevice(currentText)
|
||||
}
|
||||
}
|
||||
Text {
|
||||
id: callStateText
|
||||
text: mainWindow.call.core.state === LinphoneEnums.CallState.Paused
|
||||
|| mainWindow.call.core.state === LinphoneEnums.CallState.PausedByRemote
|
||||
? qsTr("Appel en pause") : qsTr("Appel en cours")
|
||||
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)
|
||||
}
|
||||
}
|
||||
PopupButton {
|
||||
id: listCallOptionsButton
|
||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 24 * DefaultStyle.dp
|
||||
Layout.alignment: Qt.AlignRight
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
EffectImage {
|
||||
source: 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
|
||||
|
||||
popup.contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
Button {
|
||||
leftPadding: 0
|
||||
topPadding: 5 * DefaultStyle.dp
|
||||
bottomPadding: 5 * DefaultStyle.dp
|
||||
background: Item {}
|
||||
contentItem: RowLayout {
|
||||
Image {
|
||||
source: modelData.core.paused
|
||||
? 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.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
|
||||
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 {
|
||||
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{
|
||||
// anchors.fill: delegateLayout
|
||||
// onClicked: {
|
||||
// callsModel.currentCall = modelData
|
||||
// }
|
||||
// }
|
||||
}
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -845,9 +990,7 @@ Window {
|
|||
Button {
|
||||
id: callListButton
|
||||
Layout.fillWidth: true
|
||||
background: Item {
|
||||
visible: false
|
||||
}
|
||||
background: Item {}
|
||||
contentItem: RowLayout {
|
||||
Image {
|
||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||
|
|
@ -868,9 +1011,7 @@ Window {
|
|||
Button {
|
||||
id: dialerButton
|
||||
Layout.fillWidth: true
|
||||
background: Item {
|
||||
visible: false
|
||||
}
|
||||
background: Item {}
|
||||
contentItem: RowLayout {
|
||||
Image {
|
||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||
|
|
@ -893,9 +1034,7 @@ Window {
|
|||
Layout.fillWidth: true
|
||||
enabled: mainWindow.call.core.recordable
|
||||
checkable: true
|
||||
background: Item {
|
||||
visible: false
|
||||
}
|
||||
background: Item {}
|
||||
contentItem: RowLayout {
|
||||
EffectImage {
|
||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||
|
|
@ -914,29 +1053,47 @@ Window {
|
|||
mainWindow.call.core.recording ? mainWindow.call.core.lStopRecording() : mainWindow.call.core.lStartRecording()
|
||||
}
|
||||
}
|
||||
Button {
|
||||
Control.Button {
|
||||
id: speakerButton
|
||||
Layout.fillWidth: true
|
||||
checkable: true
|
||||
background: Item {
|
||||
visible: false
|
||||
}
|
||||
background: Item {}
|
||||
contentItem: RowLayout {
|
||||
EffectImage {
|
||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 24 * DefaultStyle.dp
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: mainWindow.call.core.speakerMuted ? AppIcons.speakerSlash : AppIcons.speaker
|
||||
colorizationColor: mainWindow.call.core.speakerMuted ? DefaultStyle.danger_500main : undefined
|
||||
source: AppIcons.recordFill
|
||||
colorizationColor: mainWindow.call.core.recording ? DefaultStyle.danger_500main : undefined
|
||||
}
|
||||
Text {
|
||||
text: mainWindow.call.core.speakerMuted ? qsTr("Activer le son") : qsTr("Désactiver le son")
|
||||
color: mainWindow.call.core.speakerMuted ? DefaultStyle.danger_500main : DefaultStyle.main2_600
|
||||
color: mainWindow.call.core.recording ? DefaultStyle.danger_500main : DefaultStyle.main2_600
|
||||
text: mainWindow.call.core.recording ? qsTr("Terminer l'enregistrement") : qsTr("Enregistrer l'appel")
|
||||
}
|
||||
|
||||
}
|
||||
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 Linphone
|
||||
import UtilsCpp 1.0
|
||||
import SettingsCpp 1.0
|
||||
|
||||
Window {
|
||||
id: mainWindow
|
||||
|
|
@ -35,14 +36,14 @@ Window {
|
|||
StackView {
|
||||
id: mainWindowStackView
|
||||
anchors.fill: parent
|
||||
initialItem: accountProxy.haveAccount ? mainPage : UtilsCpp.getFirstLaunch() ? welcomePage : loginPage
|
||||
initialItem: accountProxy.haveAccount ? mainPage : SettingsCpp.getFirstLaunch() ? welcomePage : loginPage
|
||||
}
|
||||
Component {
|
||||
id: welcomePage
|
||||
WelcomePage {
|
||||
onStartButtonPressed: {
|
||||
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/RoundedBackgroundControl.qml
|
||||
view/Item/SearchBar.qml
|
||||
view/Item/Slider.qml
|
||||
view/Item/TabBar.qml
|
||||
view/Item/Text.qml
|
||||
view/Item/TextInput.qml
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ ColumnLayout {
|
|||
radius: 30 * DefaultStyle.dp
|
||||
color: DefaultStyle.main1_500_main
|
||||
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}}
|
||||
}
|
||||
RowLayout {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ ColumnLayout {
|
|||
// Usage : each item of the model list must be {text: ..., img: ...}
|
||||
// If string list, only text part of the delegate will be filled
|
||||
property var model: []
|
||||
property alias combobox: combobox
|
||||
readonly property string currentText: selectedItemText.text
|
||||
property bool enableBackgroundColors: true
|
||||
readonly property bool hasActiveFocus: combobox.activeFocus
|
||||
|
|
@ -54,6 +55,7 @@ ColumnLayout {
|
|||
id: selectedItemText
|
||||
color: combobox.enabled ? DefaultStyle.main2_600 : DefaultStyle.grey_400
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
font {
|
||||
pixelSize: 14 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
|
|
@ -67,13 +69,13 @@ ColumnLayout {
|
|||
|
||||
Component.onCompleted: {
|
||||
var index = combobox.currentIndex < 0 ? 0 : combobox.currentIndex
|
||||
if (mainItem.model[index].img) {
|
||||
selectedItemImg.source = mainItem.model[0].img
|
||||
if (mainItem.model[index] && mainItem.model[index].img) {
|
||||
selectedItemImg.source = mainItem.model[index].img
|
||||
}
|
||||
if (mainItem.model[index].text)
|
||||
selectedItemText.text = mainItem.model[0].text
|
||||
if (mainItem.model[index] && mainItem.model[index].text)
|
||||
selectedItemText.text = mainItem.model[index].text
|
||||
else if (mainItem.model[index])
|
||||
selectedItemText.text = mainItem.model[0]
|
||||
selectedItemText.text = mainItem.model[index]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,6 +134,7 @@ ColumnLayout {
|
|||
? modelData
|
||||
: ""
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
font {
|
||||
pixelSize: 14 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Loader {
|
|||
Image {
|
||||
id: image
|
||||
visible: !effect2.enabled
|
||||
source: mainItem.source
|
||||
source: mainItem.source ? mainItem.source : ""
|
||||
fillMode: mainItem.fillMode
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ MouseArea{
|
|||
preventStealing: true
|
||||
propagateComposedEvents: true
|
||||
hoverEnabled: true
|
||||
onMScaleChanged: updateScale()
|
||||
|
||||
function updateScale(){// Avoid scaling if leading outside movableArea.
|
||||
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.y = Math.max(parentTLBounds.y + margin, Math.min(parentBRBounds.y - drag.target.height - margin, drag.target.y + y - margin))
|
||||
}
|
||||
onMScaleChanged: updateScale()
|
||||
onPositionChanged: (mouse) => {
|
||||
if(dragging){
|
||||
updatePosition(mouse.x - xClicked, mouse.y - yClicked)
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ ColumnLayout {
|
|||
width: listView.width
|
||||
height: listView.height
|
||||
color: DefaultStyle.main2_300
|
||||
radius: 15 * DefaultStyle.dp
|
||||
// radius: 15 * DefaultStyle.dp
|
||||
y: listView.currentItem? listView.currentItem.y : 0
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ Button {
|
|||
closePolicy: Popup.CloseOnPressOutsideParent |Popup.CloseOnPressOutside
|
||||
|
||||
onAboutToShow: {
|
||||
if (mainApplicationWindow == undefined) return;
|
||||
var coord = mapToGlobal(mainItem.x, mainItem.y)
|
||||
if (coord.y + popup.height >= mainApplicationWindow.height) {
|
||||
y = -popup.height
|
||||
|
|
|
|||
|
|
@ -3,17 +3,17 @@ import QtQuick.Controls as Control
|
|||
import Linphone
|
||||
|
||||
Control.Control {
|
||||
width: 360 * DefaultStyle.dp
|
||||
property color backgroundColor
|
||||
topPadding: 10 * DefaultStyle.dp
|
||||
bottomPadding: 10 * DefaultStyle.dp
|
||||
leftPadding: 10 * DefaultStyle.dp
|
||||
rightPadding: 10 * DefaultStyle.dp
|
||||
id: mainItem
|
||||
// width: 360 * DefaultStyle.dp
|
||||
property color backgroundColor: DefaultStyle.grey_0
|
||||
padding: 10 * DefaultStyle.dp
|
||||
background: Rectangle {
|
||||
// anchors.fill: parent
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
anchors.fill: parent
|
||||
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