start audio call, features : pause call + blind transfer
(call window in c++)
This commit is contained in:
parent
a1d72e6382
commit
4ea1b96246
50 changed files with 1597 additions and 229 deletions
|
|
@ -26,8 +26,10 @@
|
||||||
#include <QFileSelector>
|
#include <QFileSelector>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QLibraryInfo>
|
#include <QLibraryInfo>
|
||||||
|
#include <QQmlComponent>
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
#include <QQmlFileSelector>
|
#include <QQmlFileSelector>
|
||||||
|
#include <QQuickWindow>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include "core/account/AccountCore.hpp"
|
#include "core/account/AccountCore.hpp"
|
||||||
|
|
@ -45,11 +47,14 @@
|
||||||
#include "core/singleapplication/singleapplication.h"
|
#include "core/singleapplication/singleapplication.h"
|
||||||
#include "model/object/VariantObject.hpp"
|
#include "model/object/VariantObject.hpp"
|
||||||
#include "tool/Constants.hpp"
|
#include "tool/Constants.hpp"
|
||||||
|
#include "tool/EnumsToString.hpp"
|
||||||
#include "tool/Utils.hpp"
|
#include "tool/Utils.hpp"
|
||||||
#include "tool/providers/AvatarProvider.hpp"
|
#include "tool/providers/AvatarProvider.hpp"
|
||||||
#include "tool/providers/ImageProvider.hpp"
|
#include "tool/providers/ImageProvider.hpp"
|
||||||
#include "tool/thread/Thread.hpp"
|
#include "tool/thread/Thread.hpp"
|
||||||
|
|
||||||
|
DEFINE_ABSTRACT_OBJECT(App)
|
||||||
|
|
||||||
App::App(int &argc, char *argv[])
|
App::App(int &argc, char *argv[])
|
||||||
: SingleApplication(argc, argv, true, Mode::User | Mode::ExcludeAppPath | Mode::ExcludeAppVersion) {
|
: SingleApplication(argc, argv, true, Mode::User | Mode::ExcludeAppPath | Mode::ExcludeAppVersion) {
|
||||||
mLinphoneThread = new Thread(this);
|
mLinphoneThread = new Thread(this);
|
||||||
|
|
@ -83,7 +88,7 @@ void App::init() {
|
||||||
if (mParser->isSet("qt-logs-only")) QtLogger::enableQtOnly(true);
|
if (mParser->isSet("qt-logs-only")) QtLogger::enableQtOnly(true);
|
||||||
|
|
||||||
if (!mLinphoneThread->isRunning()) {
|
if (!mLinphoneThread->isRunning()) {
|
||||||
qDebug() << "[App] Starting Thread";
|
qDebug() << log().arg("Starting Thread");
|
||||||
mLinphoneThread->start();
|
mLinphoneThread->start();
|
||||||
}
|
}
|
||||||
setQuitOnLastWindowClosed(true); // TODO: use settings to set it
|
setQuitOnLastWindowClosed(true); // TODO: use settings to set it
|
||||||
|
|
@ -96,7 +101,7 @@ void App::init() {
|
||||||
if (version.majorVersion() == 5 && version.minorVersion() == 9) selectors.push_back("5.9");
|
if (version.majorVersion() == 5 && version.minorVersion() == 9) selectors.push_back("5.9");
|
||||||
auto selector = new QQmlFileSelector(mEngine, mEngine);
|
auto selector = new QQmlFileSelector(mEngine, mEngine);
|
||||||
selector->setExtraSelectors(selectors);
|
selector->setExtraSelectors(selectors);
|
||||||
qInfo() << QStringLiteral("[App] Activated selectors:") << selector->selector()->allSelectors();
|
qInfo() << log().arg("Activated selectors:") << selector->selector()->allSelectors();
|
||||||
|
|
||||||
mEngine->addImportPath(":/");
|
mEngine->addImportPath(":/");
|
||||||
mEngine->rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath());
|
mEngine->rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath());
|
||||||
|
|
@ -110,9 +115,9 @@ void App::init() {
|
||||||
const QUrl url(u"qrc:/Linphone/view/App/Main.qml"_qs);
|
const QUrl url(u"qrc:/Linphone/view/App/Main.qml"_qs);
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
mEngine, &QQmlApplicationEngine::objectCreated, this,
|
mEngine, &QQmlApplicationEngine::objectCreated, this,
|
||||||
[url](QObject *obj, const QUrl &objUrl) {
|
[this, url](QObject *obj, const QUrl &objUrl) {
|
||||||
if (!obj && url == objUrl) {
|
if (!obj && url == objUrl) {
|
||||||
qCritical() << "[App] Main.qml couldn't be load. The app will exit";
|
qCritical() << log().arg("Main.qml couldn't be load. The app will exit");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -129,6 +134,9 @@ void App::initCppInterfaces() {
|
||||||
[](QQmlEngine *engine, QJSEngine *) -> QObject * { return new Constants(engine); });
|
[](QQmlEngine *engine, QJSEngine *) -> QObject * { return new Constants(engine); });
|
||||||
qmlRegisterSingletonType<Utils>("UtilsCpp", 1, 0, "UtilsCpp",
|
qmlRegisterSingletonType<Utils>("UtilsCpp", 1, 0, "UtilsCpp",
|
||||||
[](QQmlEngine *engine, QJSEngine *) -> QObject * { return new Utils(engine); });
|
[](QQmlEngine *engine, QJSEngine *) -> QObject * { return new Utils(engine); });
|
||||||
|
qmlRegisterSingletonType<EnumsToString>(
|
||||||
|
"EnumsToStringCpp", 1, 0, "EnumsToStringCpp",
|
||||||
|
[](QQmlEngine *engine, QJSEngine *) -> QObject * { return new EnumsToString(engine); });
|
||||||
|
|
||||||
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");
|
||||||
|
|
@ -189,9 +197,70 @@ bool App::notify(QObject *receiver, QEvent *event) {
|
||||||
try {
|
try {
|
||||||
done = QApplication::notify(receiver, event);
|
done = QApplication::notify(receiver, event);
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
qCritical() << "[App] Exception has been catch in notify";
|
qCritical() << log().arg("Exception has been catch in notify");
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
qCritical() << "[App] Generic exeption has been catch in notify";
|
qCritical() << log().arg("Generic exeption has been catch in notify");
|
||||||
}
|
}
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QQuickWindow *App::getCallsWindow(QVariant callGui) {
|
||||||
|
mustBeInMainThread(getClassName());
|
||||||
|
if (!mCallsWindow) {
|
||||||
|
const QUrl callUrl("qrc:/Linphone/view/App/CallsWindow.qml");
|
||||||
|
|
||||||
|
qInfo() << log().arg("Creating subwindow: `%1`.").arg(callUrl.toString());
|
||||||
|
|
||||||
|
QQmlComponent component(mEngine, callUrl);
|
||||||
|
if (component.isError()) {
|
||||||
|
qWarning() << component.errors();
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
qInfo() << log().arg("Subwindow status: `%1`.").arg(component.status());
|
||||||
|
|
||||||
|
QObject *object = component.createWithInitialProperties({{"call", callGui}});
|
||||||
|
Q_ASSERT(object);
|
||||||
|
if (!object) {
|
||||||
|
qCritical() << log().arg("Calls window could not be created.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
|
||||||
|
object->setParent(mEngine);
|
||||||
|
|
||||||
|
auto window = qobject_cast<QQuickWindow *>(object);
|
||||||
|
Q_ASSERT(window);
|
||||||
|
if (!window) {
|
||||||
|
qCritical() << log().arg("Calls window could not be created.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
mCallsWindow = window;
|
||||||
|
}
|
||||||
|
|
||||||
|
postModelAsync([this]() {
|
||||||
|
auto core = CoreModel::getInstance()->getCore();
|
||||||
|
auto callsNb = core->getCallsNb();
|
||||||
|
postCoreAsync([this, callsNb] { mCallsWindow->setProperty("callsCount", callsNb); });
|
||||||
|
});
|
||||||
|
mCallsWindow->setProperty("call", callGui);
|
||||||
|
return mCallsWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::closeCallsWindow() {
|
||||||
|
if (mCallsWindow) {
|
||||||
|
mCallsWindow->close();
|
||||||
|
mCallsWindow->deleteLater();
|
||||||
|
mCallsWindow = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::smartShowWindow(QQuickWindow *window) {
|
||||||
|
if (!window) return;
|
||||||
|
window->setVisible(true);
|
||||||
|
// Force show, maybe redundant with setVisible
|
||||||
|
if (window->visibility() == QWindow::Maximized) // Avoid to change visibility mode
|
||||||
|
window->showMaximized();
|
||||||
|
else window->show();
|
||||||
|
window->raise(); // Raise ensure to get focus on Mac
|
||||||
|
window->requestActivate();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,14 @@
|
||||||
|
|
||||||
#include "core/singleapplication/singleapplication.h"
|
#include "core/singleapplication/singleapplication.h"
|
||||||
#include "model/core/CoreModel.hpp"
|
#include "model/core/CoreModel.hpp"
|
||||||
|
#include "tool/AbstractObject.hpp"
|
||||||
|
|
||||||
|
class CallGui;
|
||||||
class Thread;
|
class Thread;
|
||||||
class Notifier;
|
class Notifier;
|
||||||
|
class QQuickWindow;
|
||||||
|
|
||||||
class App : public SingleApplication {
|
class App : public SingleApplication, public AbstractObject {
|
||||||
public:
|
public:
|
||||||
App(int &argc, char *argv[]);
|
App(int &argc, char *argv[]);
|
||||||
static App *getInstance();
|
static App *getInstance();
|
||||||
|
|
@ -53,6 +56,20 @@ public:
|
||||||
QMetaObject::invokeMethod(App::getInstance(), callable);
|
QMetaObject::invokeMethod(App::getInstance(), callable);
|
||||||
}
|
}
|
||||||
template <typename Func, typename... Args>
|
template <typename Func, typename... Args>
|
||||||
|
static auto postCoreSync(Func &&callable, Args &&...args) {
|
||||||
|
if (QThread::currentThread() == CoreModel::getInstance()->thread()) {
|
||||||
|
bool end = false;
|
||||||
|
postCoreAsync([&end, callable, args...]() mutable {
|
||||||
|
QMetaObject::invokeMethod(App::getInstance(), callable, args..., Qt::DirectConnection);
|
||||||
|
end = true;
|
||||||
|
});
|
||||||
|
while (!end)
|
||||||
|
qApp->processEvents();
|
||||||
|
} else {
|
||||||
|
QMetaObject::invokeMethod(App::getInstance(), callable, Qt::DirectConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename Func, typename... Args>
|
||||||
static auto postModelSync(Func &&callable, Args &&...args) {
|
static auto postModelSync(Func &&callable, Args &&...args) {
|
||||||
if (QThread::currentThread() != CoreModel::getInstance()->thread()) {
|
if (QThread::currentThread() != CoreModel::getInstance()->thread()) {
|
||||||
bool end = false;
|
bool end = false;
|
||||||
|
|
@ -73,8 +90,13 @@ public:
|
||||||
|
|
||||||
void onLoggerInitialized();
|
void onLoggerInitialized();
|
||||||
|
|
||||||
|
QQuickWindow *getCallsWindow(QVariant callGui);
|
||||||
|
void closeCallsWindow();
|
||||||
|
|
||||||
|
Q_INVOKABLE static void smartShowWindow(QQuickWindow *window);
|
||||||
|
|
||||||
QQmlApplicationEngine *mEngine = nullptr;
|
QQmlApplicationEngine *mEngine = nullptr;
|
||||||
bool notify(QObject *receiver, QEvent *event);
|
bool notify(QObject *receiver, QEvent *event) override;
|
||||||
|
|
||||||
enum class StatusCode { gRestartCode = 1000, gDeleteDataCode = 1001 };
|
enum class StatusCode { gRestartCode = 1000, gDeleteDataCode = 1001 };
|
||||||
|
|
||||||
|
|
@ -84,4 +106,9 @@ private:
|
||||||
QCommandLineParser *mParser = nullptr;
|
QCommandLineParser *mParser = nullptr;
|
||||||
Thread *mLinphoneThread = nullptr;
|
Thread *mLinphoneThread = nullptr;
|
||||||
Notifier *mNotifier = nullptr;
|
Notifier *mNotifier = nullptr;
|
||||||
|
QQuickWindow *mCallsWindow = nullptr;
|
||||||
|
// TODO : changer ce count lorsqu'on aura liste d'appels
|
||||||
|
int callsCount = 0;
|
||||||
|
|
||||||
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include "CallCore.hpp"
|
#include "CallCore.hpp"
|
||||||
#include "core/App.hpp"
|
#include "core/App.hpp"
|
||||||
#include "model/object/VariantObject.hpp"
|
#include "model/object/VariantObject.hpp"
|
||||||
|
#include "model/tool/ToolModel.hpp"
|
||||||
#include "tool/Utils.hpp"
|
#include "tool/Utils.hpp"
|
||||||
#include "tool/thread/SafeConnection.hpp"
|
#include "tool/thread/SafeConnection.hpp"
|
||||||
|
|
||||||
|
|
@ -38,15 +39,25 @@ CallCore::CallCore(const std::shared_ptr<linphone::Call> &call) : QObject(nullpt
|
||||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
||||||
// Should be call from model Thread
|
// Should be call from model Thread
|
||||||
mustBeInLinphoneThread(getClassName());
|
mustBeInLinphoneThread(getClassName());
|
||||||
|
mDir = LinphoneEnums::fromLinphone(call->getDir());
|
||||||
|
mCallModel = Utils::makeQObject_ptr<CallModel>(call);
|
||||||
|
mCallModel->setSelf(mCallModel);
|
||||||
mDuration = call->getDuration();
|
mDuration = call->getDuration();
|
||||||
mMicrophoneMuted = call->getMicrophoneMuted();
|
mMicrophoneMuted = call->getMicrophoneMuted();
|
||||||
mCallModel = Utils::makeQObject_ptr<CallModel>(call);
|
// mSpeakerMuted = call->getSpeakerMuted();
|
||||||
connect(mCallModel.get(), &CallModel::stateChanged, this, &CallCore::onStateChanged);
|
mCameraEnabled = call->cameraEnabled();
|
||||||
connect(this, &CallCore::lAccept, mCallModel.get(), &CallModel::accept);
|
mDuration = call->getDuration();
|
||||||
connect(this, &CallCore::lDecline, mCallModel.get(), &CallModel::decline);
|
|
||||||
connect(this, &CallCore::lTerminate, mCallModel.get(), &CallModel::terminate);
|
|
||||||
mCallModel->setSelf(mCallModel);
|
|
||||||
mState = LinphoneEnums::fromLinphone(call->getState());
|
mState = LinphoneEnums::fromLinphone(call->getState());
|
||||||
|
mPeerAddress = Utils::coreStringToAppString(mCallModel->getRemoteAddress()->asString());
|
||||||
|
mStatus = LinphoneEnums::fromLinphone(call->getCallLog()->getStatus());
|
||||||
|
mTransferState = LinphoneEnums::fromLinphone(call->getTransferState());
|
||||||
|
auto encryption = LinphoneEnums::fromLinphone(call->getCurrentParams()->getMediaEncryption());
|
||||||
|
auto tokenVerified = mCallModel->getAuthenticationTokenVerified();
|
||||||
|
mPeerSecured = (encryption == LinphoneEnums::MediaEncryption::Zrtp && tokenVerified) ||
|
||||||
|
encryption == LinphoneEnums::MediaEncryption::Srtp ||
|
||||||
|
encryption == LinphoneEnums::MediaEncryption::Dtls;
|
||||||
|
mPaused = mState == LinphoneEnums::CallState::Pausing || mState == LinphoneEnums::CallState::Paused ||
|
||||||
|
mState == LinphoneEnums::CallState::PausedByRemote;
|
||||||
}
|
}
|
||||||
|
|
||||||
CallCore::~CallCore() {
|
CallCore::~CallCore() {
|
||||||
|
|
@ -65,9 +76,72 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
|
||||||
mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::microphoneMutedChanged, [this](bool isMuted) {
|
mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::microphoneMutedChanged, [this](bool isMuted) {
|
||||||
mAccountModelConnection->invokeToCore([this, isMuted]() { setMicrophoneMuted(isMuted); });
|
mAccountModelConnection->invokeToCore([this, isMuted]() { setMicrophoneMuted(isMuted); });
|
||||||
});
|
});
|
||||||
|
// mAccountModelConnection->makeConnect(this, &CallCore::lSetSpeakerMuted, [this](bool isMuted) {
|
||||||
|
// mAccountModelConnection->invokeToModel([this, isMuted]() { mCallModel->setSpeakerMuted(isMuted); });
|
||||||
|
// });
|
||||||
|
// mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::speakerMutedChanged, [this](bool isMuted) {
|
||||||
|
// mAccountModelConnection->invokeToCore([this, isMuted]() { setSpeakerMuted(isMuted); });
|
||||||
|
// });
|
||||||
|
mAccountModelConnection->makeConnect(this, &CallCore::lSetCameraEnabled, [this](bool enabled) {
|
||||||
|
mAccountModelConnection->invokeToModel([this, enabled]() { mCallModel->setCameraEnabled(enabled); });
|
||||||
|
});
|
||||||
|
mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::cameraEnabledChanged, [this](bool enabled) {
|
||||||
|
mAccountModelConnection->invokeToCore([this, enabled]() { setCameraEnabled(enabled); });
|
||||||
|
});
|
||||||
mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::durationChanged, [this](int duration) {
|
mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::durationChanged, [this](int duration) {
|
||||||
mAccountModelConnection->invokeToCore([this, duration]() { setDuration(duration); });
|
mAccountModelConnection->invokeToCore([this, duration]() { setDuration(duration); });
|
||||||
});
|
});
|
||||||
|
connect(mCallModel.get(), &CallModel::stateChanged, this,
|
||||||
|
[this](linphone::Call::State state, const std::string &message) {
|
||||||
|
mAccountModelConnection->invokeToCore([this, state, message]() {
|
||||||
|
setState(LinphoneEnums::fromLinphone(state), Utils::coreStringToAppString(message));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
connect(mCallModel.get(), &CallModel::statusChanged, this, [this](linphone::Call::Status status) {
|
||||||
|
mAccountModelConnection->invokeToCore([this, status]() { setStatus(LinphoneEnums::fromLinphone(status)); });
|
||||||
|
});
|
||||||
|
mAccountModelConnection->makeConnect(this, &CallCore::lSetPaused, [this](bool paused) {
|
||||||
|
mAccountModelConnection->invokeToModel([this, paused]() { mCallModel->setPaused(paused); });
|
||||||
|
});
|
||||||
|
mAccountModelConnection->makeConnect(mCallModel.get(), &CallModel::pausedChanged, [this](bool paused) {
|
||||||
|
mAccountModelConnection->invokeToCore([this, paused]() { setPaused(paused); });
|
||||||
|
});
|
||||||
|
|
||||||
|
mAccountModelConnection->makeConnect(this, &CallCore::lTransferCall, [this](const QString &address) {
|
||||||
|
mAccountModelConnection->invokeToModel(
|
||||||
|
[this, address]() { mCallModel->transferTo(ToolModel::interpretUrl(address)); });
|
||||||
|
});
|
||||||
|
mAccountModelConnection->makeConnect(
|
||||||
|
mCallModel.get(), &CallModel::transferStateChanged,
|
||||||
|
[this](const std::shared_ptr<linphone::Call> &call, linphone::Call::State state) {
|
||||||
|
mAccountModelConnection->invokeToCore([this, state]() {
|
||||||
|
QString message;
|
||||||
|
if (state == linphone::Call::State::Error) {
|
||||||
|
message = "L'appel n'a pas pu être transféré.";
|
||||||
|
}
|
||||||
|
setTransferState(LinphoneEnums::fromLinphone(state), message);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
mAccountModelConnection->makeConnect(
|
||||||
|
mCallModel.get(), &CallModel::encryptionChanged,
|
||||||
|
[this](const std::shared_ptr<linphone::Call> &call, bool on, const std::string &authenticationToken) {
|
||||||
|
auto encryption = LinphoneEnums::fromLinphone(call->getCurrentParams()->getMediaEncryption());
|
||||||
|
auto tokenVerified = mCallModel->getAuthenticationTokenVerified();
|
||||||
|
mAccountModelConnection->invokeToCore([this, call, encryption, tokenVerified]() {
|
||||||
|
setPeerSecured((encryption == LinphoneEnums::MediaEncryption::Zrtp && tokenVerified) ||
|
||||||
|
encryption == LinphoneEnums::MediaEncryption::Srtp ||
|
||||||
|
encryption == LinphoneEnums::MediaEncryption::Dtls);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
mAccountModelConnection->makeConnect(this, &CallCore::lAccept, [this](bool withVideo) {
|
||||||
|
mAccountModelConnection->invokeToModel([this, withVideo]() { mCallModel->accept(withVideo); });
|
||||||
|
});
|
||||||
|
mAccountModelConnection->makeConnect(this, &CallCore::lDecline, [this]() {
|
||||||
|
mAccountModelConnection->invokeToModel([this]() { mCallModel->decline(); });
|
||||||
|
});
|
||||||
|
mAccountModelConnection->makeConnect(this, &CallCore::lTerminate, [this]() {
|
||||||
|
mAccountModelConnection->invokeToModel([this]() { mCallModel->terminate(); });
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LinphoneEnums::CallStatus CallCore::getStatus() const {
|
LinphoneEnums::CallStatus CallCore::getStatus() const {
|
||||||
|
|
@ -82,6 +156,18 @@ void CallCore::setStatus(LinphoneEnums::CallStatus status) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LinphoneEnums::CallDir CallCore::getDir() const {
|
||||||
|
return mDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallCore::setDir(LinphoneEnums::CallDir dir) {
|
||||||
|
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
||||||
|
if (mDir != dir) {
|
||||||
|
mDir = dir;
|
||||||
|
emit dirChanged(mDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LinphoneEnums::CallState CallCore::getState() const {
|
LinphoneEnums::CallState CallCore::getState() const {
|
||||||
return mState;
|
return mState;
|
||||||
}
|
}
|
||||||
|
|
@ -95,10 +181,6 @@ void CallCore::setState(LinphoneEnums::CallState state, const QString &message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallCore::onStateChanged(linphone::Call::State state, const std::string &message) {
|
|
||||||
setState(LinphoneEnums::fromLinphone(state), Utils::coreStringToAppString(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString CallCore::getLastErrorMessage() const {
|
QString CallCore::getLastErrorMessage() const {
|
||||||
return mLastErrorMessage;
|
return mLastErrorMessage;
|
||||||
}
|
}
|
||||||
|
|
@ -130,3 +212,47 @@ void CallCore::setMicrophoneMuted(bool isMuted) {
|
||||||
emit microphoneMutedChanged();
|
emit microphoneMutedChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CallCore::getCameraEnabled() const {
|
||||||
|
return mCameraEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallCore::setCameraEnabled(bool enabled) {
|
||||||
|
if (mCameraEnabled != enabled) {
|
||||||
|
mCameraEnabled = enabled;
|
||||||
|
emit cameraEnabledChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallCore::getPaused() const {
|
||||||
|
return mPaused;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallCore::setPaused(bool paused) {
|
||||||
|
if (mPaused != paused) {
|
||||||
|
mPaused = paused;
|
||||||
|
emit pausedChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallCore::getPeerSecured() const {
|
||||||
|
return mPeerSecured;
|
||||||
|
}
|
||||||
|
void CallCore::setPeerSecured(bool secured) {
|
||||||
|
if (mPeerSecured != secured) {
|
||||||
|
mPeerSecured = secured;
|
||||||
|
emit peerSecuredChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LinphoneEnums::CallState CallCore::getTransferState() const {
|
||||||
|
return mTransferState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallCore::setTransferState(LinphoneEnums::CallState state, const QString &message) {
|
||||||
|
if (mTransferState != state) {
|
||||||
|
mTransferState = state;
|
||||||
|
if (state == LinphoneEnums::CallState::Error) setLastErrorMessage(message);
|
||||||
|
emit transferStateChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -32,11 +32,18 @@ class SafeConnection;
|
||||||
class CallCore : public QObject, public AbstractObject {
|
class CallCore : public QObject, public AbstractObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
// Q_PROPERTY(QString peerDisplayName MEMBER mPeerDisplayName)
|
||||||
Q_PROPERTY(LinphoneEnums::CallStatus status READ getStatus NOTIFY statusChanged)
|
Q_PROPERTY(LinphoneEnums::CallStatus status READ getStatus NOTIFY statusChanged)
|
||||||
|
Q_PROPERTY(LinphoneEnums::CallDir dir READ getDir NOTIFY dirChanged)
|
||||||
Q_PROPERTY(LinphoneEnums::CallState state READ getState NOTIFY stateChanged)
|
Q_PROPERTY(LinphoneEnums::CallState state READ getState NOTIFY stateChanged)
|
||||||
Q_PROPERTY(QString lastErrorMessage READ getLastErrorMessage NOTIFY lastErrorMessageChanged)
|
Q_PROPERTY(QString lastErrorMessage READ getLastErrorMessage NOTIFY lastErrorMessageChanged)
|
||||||
Q_PROPERTY(int duration READ getDuration NOTIFY durationChanged);
|
Q_PROPERTY(int duration READ getDuration NOTIFY durationChanged)
|
||||||
Q_PROPERTY(bool microphoneMuted READ getMicrophoneMuted WRITE lSetMicrophoneMuted NOTIFY microphoneMutedChanged)
|
Q_PROPERTY(bool microphoneMuted READ getMicrophoneMuted WRITE lSetMicrophoneMuted NOTIFY microphoneMutedChanged)
|
||||||
|
Q_PROPERTY(bool cameraEnabled READ getCameraEnabled WRITE lSetCameraEnabled NOTIFY cameraEnabledChanged)
|
||||||
|
Q_PROPERTY(bool paused READ getPaused WRITE lSetPaused NOTIFY pausedChanged)
|
||||||
|
Q_PROPERTY(QString peerAddress MEMBER mPeerAddress CONSTANT)
|
||||||
|
Q_PROPERTY(bool peerSecured READ getPeerSecured WRITE setPeerSecured NOTIFY peerSecuredChanged)
|
||||||
|
Q_PROPERTY(LinphoneEnums::CallState transferState READ getTransferState NOTIFY transferStateChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Should be call from model Thread. Will be automatically in App thread after initialization
|
// Should be call from model Thread. Will be automatically in App thread after initialization
|
||||||
|
|
@ -48,9 +55,11 @@ public:
|
||||||
LinphoneEnums::CallStatus getStatus() const;
|
LinphoneEnums::CallStatus getStatus() const;
|
||||||
void setStatus(LinphoneEnums::CallStatus status);
|
void setStatus(LinphoneEnums::CallStatus status);
|
||||||
|
|
||||||
|
LinphoneEnums::CallDir getDir() const;
|
||||||
|
void setDir(LinphoneEnums::CallDir dir);
|
||||||
|
|
||||||
LinphoneEnums::CallState getState() const;
|
LinphoneEnums::CallState getState() const;
|
||||||
void setState(LinphoneEnums::CallState state, const QString &message);
|
void setState(LinphoneEnums::CallState state, const QString &message);
|
||||||
void onStateChanged(linphone::Call::State state, const std::string &message);
|
|
||||||
|
|
||||||
QString getLastErrorMessage() const;
|
QString getLastErrorMessage() const;
|
||||||
void setLastErrorMessage(const QString &message);
|
void setLastErrorMessage(const QString &message);
|
||||||
|
|
@ -61,18 +70,39 @@ public:
|
||||||
bool getMicrophoneMuted() const;
|
bool getMicrophoneMuted() const;
|
||||||
void setMicrophoneMuted(bool isMuted);
|
void setMicrophoneMuted(bool isMuted);
|
||||||
|
|
||||||
|
bool getCameraEnabled() const;
|
||||||
|
void setCameraEnabled(bool enabled);
|
||||||
|
|
||||||
|
bool getPaused() const;
|
||||||
|
void setPaused(bool paused);
|
||||||
|
|
||||||
|
bool getPeerSecured() const;
|
||||||
|
void setPeerSecured(bool secured);
|
||||||
|
|
||||||
|
LinphoneEnums::CallState getTransferState() const;
|
||||||
|
void setTransferState(LinphoneEnums::CallState state, const QString &message);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void statusChanged(LinphoneEnums::CallStatus status);
|
void statusChanged(LinphoneEnums::CallStatus status);
|
||||||
void stateChanged(LinphoneEnums::CallState state);
|
void stateChanged(LinphoneEnums::CallState state);
|
||||||
|
void dirChanged(LinphoneEnums::CallDir dir);
|
||||||
void lastErrorMessageChanged();
|
void lastErrorMessageChanged();
|
||||||
|
void peerAddressChanged();
|
||||||
void durationChanged(int duration);
|
void durationChanged(int duration);
|
||||||
void microphoneMutedChanged();
|
void microphoneMutedChanged();
|
||||||
|
void cameraEnabledChanged();
|
||||||
|
void pausedChanged();
|
||||||
|
void transferStateChanged();
|
||||||
|
void peerSecuredChanged();
|
||||||
|
|
||||||
// Linphone commands
|
// Linphone commands
|
||||||
void lAccept(bool withVideo); // Accept an incoming call
|
void lAccept(bool withVideo); // Accept an incoming call
|
||||||
void lDecline(); // Decline an incoming call
|
void lDecline(); // Decline an incoming call
|
||||||
void lTerminate(); // Hangup a call
|
void lTerminate(); // Hangup a call
|
||||||
void lSetMicrophoneMuted(bool isMuted);
|
void lSetMicrophoneMuted(bool isMuted);
|
||||||
|
void lSetCameraEnabled(bool enabled);
|
||||||
|
void lSetPaused(bool paused);
|
||||||
|
void lTransferCall(const QString &dest);
|
||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
Q_INVOKABLE void acceptWithVideo();
|
Q_INVOKABLE void acceptWithVideo();
|
||||||
|
|
@ -99,9 +129,15 @@ private:
|
||||||
std::shared_ptr<CallModel> mCallModel;
|
std::shared_ptr<CallModel> mCallModel;
|
||||||
LinphoneEnums::CallStatus mStatus;
|
LinphoneEnums::CallStatus mStatus;
|
||||||
LinphoneEnums::CallState mState;
|
LinphoneEnums::CallState mState;
|
||||||
|
LinphoneEnums::CallState mTransferState;
|
||||||
|
LinphoneEnums::CallDir mDir;
|
||||||
QString mLastErrorMessage;
|
QString mLastErrorMessage;
|
||||||
|
QString mPeerAddress;
|
||||||
|
bool mPeerSecured;
|
||||||
int mDuration = 0;
|
int mDuration = 0;
|
||||||
bool mMicrophoneMuted;
|
bool mMicrophoneMuted;
|
||||||
|
bool mCameraEnabled;
|
||||||
|
bool mPaused = false;
|
||||||
QSharedPointer<SafeConnection> mAccountModelConnection;
|
QSharedPointer<SafeConnection> mAccountModelConnection;
|
||||||
|
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ list(APPEND _LINPHONEAPP_RC_FILES data/assistant/use-app-sip-account.rc
|
||||||
"data/image/phone-selected.svg"
|
"data/image/phone-selected.svg"
|
||||||
"data/image/phone-plus.svg"
|
"data/image/phone-plus.svg"
|
||||||
"data/image/phone-disconnect.svg"
|
"data/image/phone-disconnect.svg"
|
||||||
|
"data/image/phone-transfer.svg"
|
||||||
"data/image/address-book.svg"
|
"data/image/address-book.svg"
|
||||||
"data/image/address-book-selected.svg"
|
"data/image/address-book-selected.svg"
|
||||||
"data/image/chat-teardrop-text.svg"
|
"data/image/chat-teardrop-text.svg"
|
||||||
|
|
@ -39,12 +40,23 @@ list(APPEND _LINPHONEAPP_RC_FILES data/assistant/use-app-sip-account.rc
|
||||||
"data/image/magnifying-glass.svg"
|
"data/image/magnifying-glass.svg"
|
||||||
"data/image/backspace-fill.svg"
|
"data/image/backspace-fill.svg"
|
||||||
"data/image/x.svg"
|
"data/image/x.svg"
|
||||||
|
"data/image/play.svg"
|
||||||
"data/image/incoming_call.svg"
|
"data/image/incoming_call.svg"
|
||||||
"data/image/incoming_call_missed.svg"
|
"data/image/incoming_call_missed.svg"
|
||||||
"data/image/incoming_call_rejected.svg"
|
"data/image/incoming_call_rejected.svg"
|
||||||
"data/image/outgoing_call.svg"
|
"data/image/outgoing_call.svg"
|
||||||
"data/image/outgoing_call_missed.svg"
|
"data/image/outgoing_call_missed.svg"
|
||||||
"data/image/outgoing_call_rejected.svg"
|
"data/image/outgoing_call_rejected.svg"
|
||||||
|
"data/image/microphone.svg"
|
||||||
|
"data/image/microphone-slash.svg"
|
||||||
|
"data/image/video-camera.svg"
|
||||||
|
"data/image/video-camera-slash.svg"
|
||||||
|
"data/image/speaker-high.svg"
|
||||||
|
"data/image/speaker-slash.svg"
|
||||||
|
"data/image/trusted.svg"
|
||||||
|
"data/image/randomAvatar.png"
|
||||||
|
"data/image/pause.svg"
|
||||||
|
"data/image/smiley.svg"
|
||||||
|
|
||||||
data/shaders/roundEffect.vert.qsb
|
data/shaders/roundEffect.vert.qsb
|
||||||
data/shaders/roundEffect.frag.qsb
|
data/shaders/roundEffect.frag.qsb
|
||||||
|
|
|
||||||
4
Linphone/data/image/phone-transfer.svg
Normal file
4
Linphone/data/image/phone-transfer.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="32" height="33" viewBox="0 0 32 33" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M27.985 23.3848C27.7621 25.0786 26.9303 26.6333 25.6449 27.7586C24.3595 28.884 22.7084 29.5029 21 29.4998C11.075 29.4998 3.00001 21.4248 3.00001 11.4998C2.99695 9.79142 3.61587 8.14034 4.74118 6.85493C5.86649 5.56952 7.42122 4.73769 9.11501 4.51481C9.54318 4.46242 9.97682 4.54986 10.3512 4.76409C10.7256 4.97833 11.0207 5.30787 11.1925 5.70356L13.8325 11.5986V11.6136C13.9639 11.9166 14.0181 12.2475 13.9904 12.5767C13.9627 12.9058 13.8539 13.223 13.6738 13.4998C13.6513 13.5336 13.6275 13.5648 13.6025 13.5961L11 16.6811C11.9363 18.5836 13.9263 20.5561 15.8538 21.4948L18.8963 18.9061C18.9261 18.8809 18.9574 18.8576 18.99 18.8361C19.2663 18.6508 19.5846 18.5378 19.9159 18.5072C20.2471 18.4766 20.5807 18.5295 20.8863 18.6611L20.9025 18.6686L26.7913 21.3073C27.1879 21.4783 27.5185 21.773 27.7337 22.1475C27.9489 22.522 28.037 22.9561 27.985 23.3848ZM26 23.1348C26 23.1348 25.9913 23.1348 25.9863 23.1348L20.1113 20.5023L17.0675 23.0923C17.038 23.1173 17.0071 23.1407 16.975 23.1623C16.6872 23.3543 16.3545 23.4684 16.0094 23.4934C15.6644 23.5183 15.3187 23.4534 15.0063 23.3048C12.665 22.1736 10.3313 19.8573 9.19876 17.5411C9.0488 17.2309 8.9815 16.8872 9.0034 16.5434C9.0253 16.1996 9.13565 15.8672 9.32376 15.5786C9.34496 15.5447 9.36879 15.5125 9.39501 15.4823L12 12.3936L9.37501 6.51856C9.37452 6.51357 9.37452 6.50855 9.37501 6.50356C8.16283 6.66168 7.04986 7.25626 6.24453 8.17595C5.43919 9.09564 4.99674 10.2774 5.00001 11.4998C5.00464 15.7419 6.69184 19.8088 9.69142 22.8084C12.691 25.808 16.758 27.4952 21 27.4998C22.2217 27.504 23.4031 27.0631 24.3233 26.2595C25.2436 25.4559 25.8396 24.3447 26 23.1336V23.1348Z" fill="white"/>
|
||||||
|
<path d="M15.3434 8.1709C15.3434 8.0624 15.3647 7.95495 15.4062 7.8547C15.4477 7.75445 15.5085 7.66336 15.5852 7.58664C15.662 7.50991 15.7531 7.44907 15.8533 7.40757C15.9536 7.36608 16.061 7.34475 16.1695 7.34481L21.1822 7.34554L19.6723 5.83568C19.5175 5.68084 19.4305 5.47084 19.4305 5.25187C19.4305 5.0329 19.5175 4.8229 19.6723 4.66807C19.8272 4.51323 20.0372 4.42625 20.2561 4.42625C20.4751 4.42625 20.6851 4.51323 20.8399 4.66807L23.759 7.58709C23.9138 7.74193 24.0008 7.95193 24.0008 8.1709C24.0008 8.38987 23.9138 8.59987 23.759 8.7547L20.8399 11.6737C20.6851 11.8286 20.4751 11.9155 20.2561 11.9155C20.0372 11.9155 19.8272 11.8286 19.6723 11.6737C19.5175 11.5189 19.4305 11.3089 19.4305 11.0899C19.4305 10.871 19.5175 10.661 19.6723 10.5061L21.1822 8.99625L16.1695 8.99698C16.061 8.99704 15.9536 8.97572 15.8533 8.93422C15.7531 8.89273 15.662 8.83188 15.5852 8.75516C15.5085 8.67844 15.4477 8.58735 15.4062 8.4871C15.3647 8.38685 15.3434 8.2794 15.3434 8.1709Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Linphone/data/image/randomAvatar.png
Normal file
BIN
Linphone/data/image/randomAvatar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
|
|
@ -23,6 +23,7 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "model/core/CoreModel.hpp"
|
#include "model/core/CoreModel.hpp"
|
||||||
|
#include "tool/Utils.hpp"
|
||||||
|
|
||||||
DEFINE_ABSTRACT_OBJECT(CallModel)
|
DEFINE_ABSTRACT_OBJECT(CallModel)
|
||||||
|
|
||||||
|
|
@ -41,7 +42,6 @@ CallModel::~CallModel() {
|
||||||
|
|
||||||
void CallModel::accept(bool withVideo) {
|
void CallModel::accept(bool withVideo) {
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
|
||||||
auto core = CoreModel::getInstance()->getCore();
|
auto core = CoreModel::getInstance()->getCore();
|
||||||
auto params = core->createCallParams(mMonitor);
|
auto params = core->createCallParams(mMonitor);
|
||||||
params->enableVideo(withVideo);
|
params->enableVideo(withVideo);
|
||||||
|
|
@ -68,12 +68,53 @@ void CallModel::terminate() {
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
mMonitor->terminate();
|
mMonitor->terminate();
|
||||||
}
|
}
|
||||||
|
void CallModel::setPaused(bool paused) {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
if (paused) {
|
||||||
|
auto status = mMonitor->pause();
|
||||||
|
if (status != -1) emit pausedChanged(paused);
|
||||||
|
} else {
|
||||||
|
auto status = mMonitor->resume();
|
||||||
|
if (status != -1) emit pausedChanged(paused);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::transferTo(const std::shared_ptr<linphone::Address> &address) {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
if (mMonitor->transferTo(address) == -1)
|
||||||
|
qWarning() << log()
|
||||||
|
.arg(QStringLiteral("Unable to transfer: `%1`."))
|
||||||
|
.arg(Utils::coreStringToAppString(address->asString()));
|
||||||
|
}
|
||||||
|
|
||||||
void CallModel::setMicrophoneMuted(bool isMuted) {
|
void CallModel::setMicrophoneMuted(bool isMuted) {
|
||||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
mMonitor->setMicrophoneMuted(isMuted);
|
mMonitor->setMicrophoneMuted(isMuted);
|
||||||
emit microphoneMutedChanged(isMuted);
|
emit microphoneMutedChanged(isMuted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CallModel::setSpeakerMuted(bool isMuted) {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
mMonitor->setSpeakerMuted(isMuted);
|
||||||
|
emit speakerMutedChanged(isMuted);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::setCameraEnabled(bool enabled) {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
mMonitor->enableCamera(enabled);
|
||||||
|
emit cameraEnabledChanged(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const linphone::Address> CallModel::getRemoteAddress() {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
return mMonitor->getRemoteAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallModel::getAuthenticationTokenVerified() {
|
||||||
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||||
|
return mMonitor->getAuthenticationTokenVerified();
|
||||||
|
}
|
||||||
|
|
||||||
void CallModel::onDtmfReceived(const std::shared_ptr<linphone::Call> &call, int dtmf) {
|
void CallModel::onDtmfReceived(const std::shared_ptr<linphone::Call> &call, int dtmf) {
|
||||||
emit dtmfReceived(call, dtmf);
|
emit dtmfReceived(call, dtmf);
|
||||||
}
|
}
|
||||||
|
|
@ -108,6 +149,14 @@ void CallModel::onStateChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
emit stateChanged(state, message);
|
emit stateChanged(state, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CallModel::onStatusChanged(const std::shared_ptr<linphone::Call> &call, linphone::Call::Status status) {
|
||||||
|
emit statusChanged(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallModel::onDirChanged(const std::shared_ptr<linphone::Call> &call, linphone::Call::Dir dir) {
|
||||||
|
emit dirChanged(dir);
|
||||||
|
}
|
||||||
|
|
||||||
void CallModel::onStatsUpdated(const std::shared_ptr<linphone::Call> &call,
|
void CallModel::onStatsUpdated(const std::shared_ptr<linphone::Call> &call,
|
||||||
const std::shared_ptr<const linphone::CallStats> &stats) {
|
const std::shared_ptr<const linphone::CallStats> &stats) {
|
||||||
emit statsUpdated(call, stats);
|
emit statsUpdated(call, stats);
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,20 @@ public:
|
||||||
void terminate();
|
void terminate();
|
||||||
|
|
||||||
void setMicrophoneMuted(bool isMuted);
|
void setMicrophoneMuted(bool isMuted);
|
||||||
|
void setSpeakerMuted(bool isMuted);
|
||||||
|
void setCameraEnabled(bool enabled);
|
||||||
|
void setPaused(bool paused);
|
||||||
|
void transferTo(const std::shared_ptr<linphone::Address> &address);
|
||||||
|
|
||||||
|
std::shared_ptr<const linphone::Address> getRemoteAddress();
|
||||||
|
bool getAuthenticationTokenVerified();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void microphoneMutedChanged(bool isMuted);
|
void microphoneMutedChanged(bool isMuted);
|
||||||
|
void speakerMutedChanged(bool isMuted);
|
||||||
|
void cameraEnabledChanged(bool enabled);
|
||||||
void durationChanged(int);
|
void durationChanged(int);
|
||||||
|
void pausedChanged(bool paused);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTimer mDurationTimer;
|
QTimer mDurationTimer;
|
||||||
|
|
@ -67,6 +77,8 @@ private:
|
||||||
virtual void onStateChanged(const std::shared_ptr<linphone::Call> &call,
|
virtual void onStateChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
linphone::Call::State state,
|
linphone::Call::State state,
|
||||||
const std::string &message) override;
|
const std::string &message) override;
|
||||||
|
virtual void onStatusChanged(const std::shared_ptr<linphone::Call> &call, linphone::Call::Status status);
|
||||||
|
virtual void onDirChanged(const std::shared_ptr<linphone::Call> &call, linphone::Call::Dir dir);
|
||||||
virtual void onStatsUpdated(const std::shared_ptr<linphone::Call> &call,
|
virtual void onStatsUpdated(const std::shared_ptr<linphone::Call> &call,
|
||||||
const std::shared_ptr<const linphone::CallStats> &stats) override;
|
const std::shared_ptr<const linphone::CallStats> &stats) override;
|
||||||
virtual void onTransferStateChanged(const std::shared_ptr<linphone::Call> &call,
|
virtual void onTransferStateChanged(const std::shared_ptr<linphone::Call> &call,
|
||||||
|
|
@ -94,6 +106,8 @@ signals:
|
||||||
void infoMessageReceived(const std::shared_ptr<linphone::Call> &call,
|
void infoMessageReceived(const std::shared_ptr<linphone::Call> &call,
|
||||||
const std::shared_ptr<const linphone::InfoMessage> &message);
|
const std::shared_ptr<const linphone::InfoMessage> &message);
|
||||||
void stateChanged(linphone::Call::State state, const std::string &message);
|
void stateChanged(linphone::Call::State state, const std::string &message);
|
||||||
|
void statusChanged(linphone::Call::Status status);
|
||||||
|
void dirChanged(linphone::Call::Dir dir);
|
||||||
void statsUpdated(const std::shared_ptr<linphone::Call> &call,
|
void statsUpdated(const std::shared_ptr<linphone::Call> &call,
|
||||||
const std::shared_ptr<const linphone::CallStats> &stats);
|
const std::shared_ptr<const linphone::CallStats> &stats);
|
||||||
void transferStateChanged(const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
|
void transferStateChanged(const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ void CoreModel::start() {
|
||||||
setPathAfterStart();
|
setPathAfterStart();
|
||||||
mCore->enableFriendListSubscription(true);
|
mCore->enableFriendListSubscription(true);
|
||||||
mCore->enableRecordAware(true);
|
mCore->enableRecordAware(true);
|
||||||
|
mCore->getCallsNb();
|
||||||
mIterateTimer->start();
|
mIterateTimer->start();
|
||||||
}
|
}
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
list(APPEND _LINPHONEAPP_SOURCES
|
list(APPEND _LINPHONEAPP_SOURCES
|
||||||
tool/Constants.cpp
|
tool/Constants.cpp
|
||||||
|
tool/EnumsToString.cpp
|
||||||
tool/Utils.cpp
|
tool/Utils.cpp
|
||||||
|
|
||||||
tool/LinphoneEnums.cpp
|
tool/LinphoneEnums.cpp
|
||||||
|
|
|
||||||
28
Linphone/tool/EnumsToString.cpp
Normal file
28
Linphone/tool/EnumsToString.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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 "EnumsToString.hpp"
|
||||||
|
|
||||||
|
#include "core/App.hpp"
|
||||||
|
#include "model/call/CallModel.hpp"
|
||||||
|
#include "model/object/VariantObject.hpp"
|
||||||
|
#include "model/tool/ToolModel.hpp"
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
50
Linphone/tool/EnumsToString.hpp
Normal file
50
Linphone/tool/EnumsToString.hpp
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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 ENUMSTOSTRING_H_
|
||||||
|
#define ENUMSTOSTRING_H_
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "LinphoneEnums.hpp"
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Class to make the link between qml and LinphoneEnums functions
|
||||||
|
* TODO : transform LinphoneEnums into a class so we can delete this one
|
||||||
|
*/
|
||||||
|
|
||||||
|
class EnumsToString : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
EnumsToString(QObject *parent = nullptr) : QObject(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_INVOKABLE QString dirToString(const LinphoneEnums::CallDir &data) {
|
||||||
|
return LinphoneEnums::toString(data);
|
||||||
|
}
|
||||||
|
Q_INVOKABLE QString statusToString(const LinphoneEnums::CallStatus &data) {
|
||||||
|
return LinphoneEnums::toString(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ENUMSTOSTRING_H_
|
||||||
|
|
@ -115,6 +115,22 @@ QString LinphoneEnums::toString(const LinphoneEnums::CallStatus &data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LinphoneEnums::CallDir LinphoneEnums::fromLinphone(const linphone::Call::Dir &data) {
|
||||||
|
return static_cast<LinphoneEnums::CallDir>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
linphone::Call::Dir LinphoneEnums::toLinphone(const LinphoneEnums::CallDir &data) {
|
||||||
|
return static_cast<linphone::Call::Dir>(data);
|
||||||
|
}
|
||||||
|
QString LinphoneEnums::toString(const LinphoneEnums::CallDir &data) {
|
||||||
|
switch (data) {
|
||||||
|
case LinphoneEnums::CallDir::Incoming:
|
||||||
|
return "Incoming";
|
||||||
|
case LinphoneEnums::CallDir::Outgoing:
|
||||||
|
return "Outgoing";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
linphone::Conference::Layout LinphoneEnums::toLinphone(const LinphoneEnums::ConferenceLayout &layout) {
|
linphone::Conference::Layout LinphoneEnums::toLinphone(const LinphoneEnums::ConferenceLayout &layout) {
|
||||||
if (layout != LinphoneEnums::ConferenceLayout::AudioOnly) return static_cast<linphone::Conference::Layout>(layout);
|
if (layout != LinphoneEnums::ConferenceLayout::AudioOnly) return static_cast<linphone::Conference::Layout>(layout);
|
||||||
else return linphone::Conference::Layout::Grid; // Audio Only mode
|
else return linphone::Conference::Layout::Grid; // Audio Only mode
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,13 @@ linphone::Call::Status toLinphone(const LinphoneEnums::CallStatus &data);
|
||||||
LinphoneEnums::CallStatus fromLinphone(const linphone::Call::Status &data);
|
LinphoneEnums::CallStatus fromLinphone(const linphone::Call::Status &data);
|
||||||
QString toString(const LinphoneEnums::CallStatus &data);
|
QString toString(const LinphoneEnums::CallStatus &data);
|
||||||
|
|
||||||
|
enum class CallDir { Outgoing = int(linphone::Call::Dir::Outgoing), Incoming = int(linphone::Call::Dir::Incoming) };
|
||||||
|
Q_ENUM_NS(CallDir)
|
||||||
|
|
||||||
|
linphone::Call::Dir toLinphone(const LinphoneEnums::CallDir &data);
|
||||||
|
LinphoneEnums::CallDir fromLinphone(const linphone::Call::Dir &data);
|
||||||
|
QString toString(const LinphoneEnums::CallDir &data);
|
||||||
|
|
||||||
enum class ConferenceLayout {
|
enum class ConferenceLayout {
|
||||||
Grid = int(linphone::Conference::Layout::Grid),
|
Grid = int(linphone::Conference::Layout::Grid),
|
||||||
ActiveSpeaker = int(linphone::Conference::Layout::ActiveSpeaker),
|
ActiveSpeaker = int(linphone::Conference::Layout::ActiveSpeaker),
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "model/tool/ToolModel.hpp"
|
#include "model/tool/ToolModel.hpp"
|
||||||
#include "tool/providers/AvatarProvider.hpp"
|
#include "tool/providers/AvatarProvider.hpp"
|
||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
|
#include <QQuickWindow>
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
|
|
@ -81,7 +82,13 @@ VariantObject *Utils::createCall(const QString &sipAddress,
|
||||||
data->makeRequest([sipAddress, prepareTransfertAddress, headers]() {
|
data->makeRequest([sipAddress, prepareTransfertAddress, headers]() {
|
||||||
auto call = ToolModel::createCall(sipAddress, prepareTransfertAddress, headers);
|
auto call = ToolModel::createCall(sipAddress, prepareTransfertAddress, headers);
|
||||||
if (call) {
|
if (call) {
|
||||||
return QVariant::fromValue(new CallGui(call));
|
auto callGui = QVariant::fromValue(new CallGui(call));
|
||||||
|
App::postCoreSync([callGui]() {
|
||||||
|
auto app = App::getInstance();
|
||||||
|
auto window = app->getCallsWindow(callGui);
|
||||||
|
window->show();
|
||||||
|
});
|
||||||
|
return callGui;
|
||||||
} else return QVariant();
|
} else return QVariant();
|
||||||
});
|
});
|
||||||
data->requestValue();
|
data->requestValue();
|
||||||
|
|
@ -89,6 +96,10 @@ VariantObject *Utils::createCall(const QString &sipAddress,
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Utils::closeCallsWindow() {
|
||||||
|
App::getInstance()->closeCallsWindow();
|
||||||
|
}
|
||||||
|
|
||||||
VariantObject *Utils::haveAccount() {
|
VariantObject *Utils::haveAccount() {
|
||||||
VariantObject *result = new VariantObject();
|
VariantObject *result = new VariantObject();
|
||||||
|
|
||||||
|
|
@ -134,3 +145,36 @@ QString Utils::createAvatar(const QUrl &fileUrl) {
|
||||||
}
|
}
|
||||||
return fileUri;
|
return fileUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Utils::formatElapsedTime(int seconds) {
|
||||||
|
// s, m, h, d, W, M, Y
|
||||||
|
// 1, 60, 3600, 86400, 604800, 2592000, 31104000
|
||||||
|
auto y = floor(seconds / 31104000);
|
||||||
|
if (y > 0) return QString::number(y) + " years";
|
||||||
|
auto M = floor(seconds / 2592000);
|
||||||
|
if (M > 0) return QString::number(M) + " months";
|
||||||
|
auto w = floor(seconds / 604800);
|
||||||
|
if (w > 0) return QString::number(w) + " week";
|
||||||
|
auto d = floor(seconds / 86400);
|
||||||
|
if (d > 0) return QString::number(d) + " days";
|
||||||
|
|
||||||
|
auto h = floor(seconds / 3600);
|
||||||
|
auto m = floor((seconds - h * 3600) / 60);
|
||||||
|
auto s = seconds - h * 3600 - m * 60;
|
||||||
|
|
||||||
|
QString hours, min, sec;
|
||||||
|
|
||||||
|
if (h < 10 && h > 0) {
|
||||||
|
hours = "0" + QString::number(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m < 10) {
|
||||||
|
min = "0" + QString::number(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s < 10) {
|
||||||
|
sec = "0" + QString::number(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (h == 0 ? "" : hours + ":") + min + ":" + sec;
|
||||||
|
}
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
#endif // if defined(__GNUC__) && __GNUC__ >= 7
|
#endif // if defined(__GNUC__) && __GNUC__ >= 7
|
||||||
#endif // ifndef UTILS_NO_BREAK
|
#endif // ifndef UTILS_NO_BREAK
|
||||||
|
|
||||||
|
class QQuickWindow;
|
||||||
class VariantObject;
|
class VariantObject;
|
||||||
|
|
||||||
class Utils : public QObject {
|
class Utils : public QObject {
|
||||||
|
|
@ -53,8 +54,10 @@ public:
|
||||||
Q_INVOKABLE static VariantObject *createCall(const QString &sipAddress,
|
Q_INVOKABLE static VariantObject *createCall(const QString &sipAddress,
|
||||||
const QString &prepareTransfertAddress = "",
|
const QString &prepareTransfertAddress = "",
|
||||||
const QHash<QString, QString> &headers = {});
|
const QHash<QString, QString> &headers = {});
|
||||||
|
Q_INVOKABLE static void closeCallsWindow();
|
||||||
Q_INVOKABLE static VariantObject *haveAccount();
|
Q_INVOKABLE static VariantObject *haveAccount();
|
||||||
Q_INVOKABLE static QString createAvatar(const QUrl &fileUrl); // Return the avatar path
|
Q_INVOKABLE static QString createAvatar(const QUrl &fileUrl); // Return the avatar path
|
||||||
|
Q_INVOKABLE static QString formatElapsedTime(int seconds); // Return the elapsed time formated
|
||||||
|
|
||||||
static inline QString coreStringToAppString(const std::string &str) {
|
static inline QString coreStringToAppString(const std::string &str) {
|
||||||
if (Constants::LinphoneLocaleEncoding == QString("UTF-8")) return QString::fromStdString(str);
|
if (Constants::LinphoneLocaleEncoding == QString("UTF-8")) return QString::fromStdString(str);
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ ImageAsyncImageResponse::ImageAsyncImageResponse(const QString &id, const QSize
|
||||||
QString path = ":/data/image/";
|
QString path = ":/data/image/";
|
||||||
QStringList filters;
|
QStringList filters;
|
||||||
filters << "*.svg";
|
filters << "*.svg";
|
||||||
|
filters << "*.png";
|
||||||
QDir imageDir(path);
|
QDir imageDir(path);
|
||||||
if (!imageDir.exists()) {
|
if (!imageDir.exists()) {
|
||||||
qDebug() << QStringLiteral("[ImageProvider] Dir doesn't exist: `%1`.").arg(path);
|
qDebug() << QStringLiteral("[ImageProvider] Dir doesn't exist: `%1`.").arg(path);
|
||||||
|
|
|
||||||
531
Linphone/view/App/CallsWindow.qml
Normal file
531
Linphone/view/App/CallsWindow.qml
Normal file
|
|
@ -0,0 +1,531 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Effects
|
||||||
|
import QtQuick.Controls as Control
|
||||||
|
import Linphone
|
||||||
|
import EnumsToStringCpp 1.0
|
||||||
|
import UtilsCpp 1.0
|
||||||
|
|
||||||
|
Window {
|
||||||
|
id: mainWindow
|
||||||
|
width: 1512 * DefaultStyle.dp
|
||||||
|
height: 982 * DefaultStyle.dp
|
||||||
|
|
||||||
|
property CallGui call
|
||||||
|
|
||||||
|
property bool isInContactList: false
|
||||||
|
|
||||||
|
property int callsCount: 0
|
||||||
|
onCallsCountChanged: console.log("calls count", callsCount)
|
||||||
|
|
||||||
|
property var peerName: UtilsCpp.getDisplayName(call.core.peerAddress)
|
||||||
|
property string peerNameText: peerName ? peerName.value : ""
|
||||||
|
|
||||||
|
// TODO : remove this, for debug only
|
||||||
|
property var callState: call && call.core.state
|
||||||
|
onCallStateChanged: {
|
||||||
|
console.log("State:", callState)
|
||||||
|
if (callState === LinphoneEnums.CallState.Error || callState === LinphoneEnums.CallState.End) {
|
||||||
|
endCall()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClosing: {
|
||||||
|
endCall()
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: autoCloseWindow
|
||||||
|
interval: 2000
|
||||||
|
onTriggered: {
|
||||||
|
UtilsCpp.closeCallsWindow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function endCall() {
|
||||||
|
console.log("remaining calls before ending", mainWindow.callsCount)
|
||||||
|
callStatusText.text = qsTr("End of the call")
|
||||||
|
if (call) call.core.lTerminate()
|
||||||
|
if (callsCount === 1) {
|
||||||
|
bottomButtonsLayout.setButtonsEnabled(false)
|
||||||
|
autoCloseWindow.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component BottomButton : Button {
|
||||||
|
required property string enabledIcon
|
||||||
|
property string disabledIcon
|
||||||
|
id: bottomButton
|
||||||
|
enabled: call != undefined
|
||||||
|
padding: 18 * DefaultStyle.dp
|
||||||
|
checkable: true
|
||||||
|
background: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: bottomButton.enabled
|
||||||
|
? bottomButton.checked
|
||||||
|
? disabledIcon
|
||||||
|
? DefaultStyle.grey_0
|
||||||
|
: DefaultStyle.main2_400
|
||||||
|
: bottomButton.pressed
|
||||||
|
? DefaultStyle.main2_400
|
||||||
|
: DefaultStyle.grey_500
|
||||||
|
: DefaultStyle.grey_600
|
||||||
|
radius: 71 * DefaultStyle.dp
|
||||||
|
}
|
||||||
|
contentItem: EffectImage {
|
||||||
|
image.source: disabledIcon && bottomButton.checked ? disabledIcon : enabledIcon
|
||||||
|
anchors.fill: parent
|
||||||
|
image.width: 32 * DefaultStyle.dp
|
||||||
|
image.height: 32 * DefaultStyle.dp
|
||||||
|
colorizationColor: disabledIcon && bottomButton.checked ? DefaultStyle.main2_0 : DefaultStyle.grey_0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Control.Popup {
|
||||||
|
id: waitingPopup
|
||||||
|
visible: mainWindow.call.core.transferState === LinphoneEnums.CallState.OutgoingInit
|
||||||
|
|| mainWindow.call.core.transferState === LinphoneEnums.CallState.OutgoingProgress
|
||||||
|
|| mainWindow.call.core.transferState === LinphoneEnums.CallState.OutgoingRinging || false
|
||||||
|
modal: true
|
||||||
|
closePolicy: Control.Popup.NoAutoClose
|
||||||
|
anchors.centerIn: parent
|
||||||
|
padding: 20
|
||||||
|
background: Item {
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
Rectangle {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
height: parent.height + 2
|
||||||
|
color: DefaultStyle.main1_500_main
|
||||||
|
radius: 15
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
id: mainBackground
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
BusyIndicator{
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: qsTr("Transfert en cours, veuillez patienter")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Control.Popup {
|
||||||
|
id: transferErrorPopup
|
||||||
|
visible: mainWindow.call.core.transferState === LinphoneEnums.CallState.Error
|
||||||
|
modal: true
|
||||||
|
closePolicy: Control.Popup.NoAutoClose
|
||||||
|
x : parent.x + parent.width - width
|
||||||
|
y : parent.y + parent.height - height
|
||||||
|
padding: 20
|
||||||
|
background: Item {
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
Rectangle {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
height: parent.height + 2
|
||||||
|
color: DefaultStyle.danger_500
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
id: transferErrorBackground
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: 15
|
||||||
|
}
|
||||||
|
MultiEffect {
|
||||||
|
anchors.fill: transferErrorBackground
|
||||||
|
shadowEnabled: true
|
||||||
|
shadowColor: DefaultStyle.grey_900
|
||||||
|
shadowBlur: 10
|
||||||
|
// shadowOpacity: 0.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
Text {
|
||||||
|
text: qsTr("Erreur de transfert")
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: qsTr("Le transfert d'appel a échoué.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: DefaultStyle.ongoingCallWindowColor
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: 5
|
||||||
|
anchors.bottomMargin: 5
|
||||||
|
Item {
|
||||||
|
Layout.margins: 10
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.minimumHeight: 25
|
||||||
|
RowLayout {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: 10
|
||||||
|
EffectImage {
|
||||||
|
id: callStatusIcon
|
||||||
|
image.fillMode: Image.PreserveAspectFit
|
||||||
|
image.width: 15
|
||||||
|
image.height: 15
|
||||||
|
image.sourceSize.width: 15
|
||||||
|
image.sourceSize.height: 15
|
||||||
|
image.source: (mainWindow.call.core.state === LinphoneEnums.CallState.Paused
|
||||||
|
|| mainWindow.callState === LinphoneEnums.CallState.PausedByRemote)
|
||||||
|
? AppIcons.pause
|
||||||
|
: (mainWindow.callState === LinphoneEnums.CallState.End
|
||||||
|
|| mainWindow.callState === LinphoneEnums.CallState.Released)
|
||||||
|
? AppIcons.endCall
|
||||||
|
: mainWindow.call.core.dir === LinphoneEnums.CallDir.Outgoing
|
||||||
|
? AppIcons.outgoingCall
|
||||||
|
: AppIcons.incomingCall
|
||||||
|
colorizationColor: mainWindow.callState === LinphoneEnums.CallState.Paused
|
||||||
|
|| mainWindow.callState === LinphoneEnums.CallState.PausedByRemote || mainWindow.callState === LinphoneEnums.CallState.End
|
||||||
|
|| mainWindow.callState === LinphoneEnums.CallState.Released ? DefaultStyle.danger_500 : undefined
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id: callStatusText
|
||||||
|
text: (mainWindow.callState === LinphoneEnums.CallState.End || mainWindow.callState === LinphoneEnums.CallState.Released)
|
||||||
|
? qsTr("End of the call")
|
||||||
|
: (mainWindow.callState === LinphoneEnums.CallState.Paused || mainWindow.callState === LinphoneEnums.CallState.PausedByRemote)
|
||||||
|
? qsTr("Appel mis en pause")
|
||||||
|
: EnumsToStringCpp.dirToString(mainWindow.call.core.dir) + qsTr(" call")
|
||||||
|
color: DefaultStyle.grey_0
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
visible: mainWindow.callState === LinphoneEnums.CallState.Connected
|
||||||
|
|| mainWindow.callState === LinphoneEnums.CallState.StreamsRunning
|
||||||
|
Layout.preferredHeight: parent.height
|
||||||
|
Layout.preferredWidth: 2
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: UtilsCpp.formatElapsedTime(mainWindow.call.core.duration)
|
||||||
|
color: DefaultStyle.grey_0
|
||||||
|
visible: mainWindow.callState === LinphoneEnums.CallState.Connected
|
||||||
|
|| mainWindow.callState === LinphoneEnums.CallState.StreamsRunning
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Control.Control {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
topPadding: 8
|
||||||
|
bottomPadding: 8
|
||||||
|
leftPadding: 10
|
||||||
|
rightPadding: 10
|
||||||
|
visible: mainWindow.call.core.peerSecured
|
||||||
|
onVisibleChanged: console.log("peer secured", mainWindow.call.core.peerSecured)
|
||||||
|
background: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
border.color: DefaultStyle.info_500_main
|
||||||
|
radius: 15
|
||||||
|
}
|
||||||
|
contentItem: RowLayout {
|
||||||
|
Image {
|
||||||
|
source: AppIcons.trusted
|
||||||
|
Layout.preferredWidth: 15
|
||||||
|
Layout.preferredHeight: 15
|
||||||
|
sourceSize.width: 15
|
||||||
|
sourceSize.height: 15
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: "This call is completely secured"
|
||||||
|
color: DefaultStyle.info_500_main
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
Control.Control {
|
||||||
|
id: centerItem
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredWidth: 1059 * DefaultStyle.dp
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.leftMargin: 10
|
||||||
|
Layout.rightMargin: 10
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
background: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: DefaultStyle.ongoingCallBackgroundColor
|
||||||
|
radius: 15
|
||||||
|
}
|
||||||
|
contentItem: Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
StackLayout {
|
||||||
|
id: centerLayout
|
||||||
|
anchors.fill: parent
|
||||||
|
Connections {
|
||||||
|
target: mainWindow
|
||||||
|
onCallStateChanged: {
|
||||||
|
if (mainWindow.callState === LinphoneEnums.CallState.Error) {
|
||||||
|
centerLayout.currentIndex = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
id: audioCallItem
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.preferredWidth: parent.width
|
||||||
|
Layout.preferredHeight: parent.height
|
||||||
|
Timer {
|
||||||
|
id: secondsTimer
|
||||||
|
interval: 1000
|
||||||
|
repeat: true
|
||||||
|
onTriggered: waitingTime.seconds += 1
|
||||||
|
}
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 30
|
||||||
|
visible: mainWindow.callState == LinphoneEnums.CallState.OutgoingInit
|
||||||
|
|| mainWindow.callState == LinphoneEnums.CallState.OutgoingProgress
|
||||||
|
|| mainWindow.callState == LinphoneEnums.CallState.OutgoingRinging
|
||||||
|
|| mainWindow.callState == LinphoneEnums.CallState.OutgoingEarlyMedia
|
||||||
|
|| mainWindow.callState == LinphoneEnums.CallState.IncomingReceived
|
||||||
|
BusyIndicator {
|
||||||
|
indicatorColor: DefaultStyle.main2_100
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id: waitingTime
|
||||||
|
property int seconds
|
||||||
|
text: UtilsCpp.formatElapsedTime(seconds)
|
||||||
|
color: DefaultStyle.grey_0
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.pointSize: DefaultStyle.ongoingCallElapsedTimeSize
|
||||||
|
Component.onCompleted: {
|
||||||
|
secondsTimer.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: 2
|
||||||
|
// Avatar {
|
||||||
|
// Layout.alignment: Qt.AlignCenter
|
||||||
|
// visible: mainWindow.isInContactList
|
||||||
|
// image.source: AppIcons.avatar
|
||||||
|
// size: 100
|
||||||
|
// }
|
||||||
|
// DefaultAvatar {
|
||||||
|
// id: defaultAvatar
|
||||||
|
// Layout.alignment: Qt.AlignCenter
|
||||||
|
// visible: !mainWindow.isInContactList
|
||||||
|
// initials:{
|
||||||
|
// var usernameList = mainWindow.peerNameText.split(' ')
|
||||||
|
// for (var i = 0; i < usernameList.length; ++i) {
|
||||||
|
// initials += usernameList[i][0]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Connections {
|
||||||
|
// target: mainWindow
|
||||||
|
// onPeerNameChanged: {
|
||||||
|
// defaultAvatar.initials = ""
|
||||||
|
// var usernameList = mainWindow.peerName.value.split(' ')
|
||||||
|
// for (var i = 0; i < usernameList.length; ++i) {
|
||||||
|
// defaultAvatar.initials += usernameList[i][0]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// width: 100
|
||||||
|
// height: 100
|
||||||
|
// }
|
||||||
|
Text {
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
Layout.topMargin: 15
|
||||||
|
visible: mainWindow.peerNameText.length > 0
|
||||||
|
text: mainWindow.peerNameText
|
||||||
|
color: DefaultStyle.grey_0
|
||||||
|
font {
|
||||||
|
pointSize: DefaultStyle.ongoingCallNameSize
|
||||||
|
capitalization: Font.Capitalize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
text: mainWindow.call.core.peerAddress
|
||||||
|
color: DefaultStyle.grey_0
|
||||||
|
font.pointSize: DefaultStyle.ongoingCallAddressSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Image {
|
||||||
|
id: videoCallItem
|
||||||
|
Layout.preferredWidth: parent.width
|
||||||
|
Layout.preferredHeight: parent.height
|
||||||
|
}
|
||||||
|
ColumnLayout {
|
||||||
|
id: userNotFoundLayout
|
||||||
|
Layout.preferredWidth: parent.width
|
||||||
|
Layout.preferredHeight: parent.height
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
Text {
|
||||||
|
text: qsTr(mainWindow.call.core.lastErrorMessage)
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
color: DefaultStyle.grey_0
|
||||||
|
font.pointSize: DefaultStyle.ongoingCallNameSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
anchors.bottomMargin: 10
|
||||||
|
text: mainWindow.peerNameText
|
||||||
|
color: DefaultStyle.grey_0
|
||||||
|
font.pointSize: DefaultStyle.ongoingCallAddressSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OngoingCallRightPanel {
|
||||||
|
id: rightPanel
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.preferredWidth: 393 * DefaultStyle.dp
|
||||||
|
property int currentIndex: 0
|
||||||
|
Layout.rightMargin: 10
|
||||||
|
visible: false
|
||||||
|
headerContent: StackLayout {
|
||||||
|
currentIndex: rightPanel.currentIndex
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
Text {
|
||||||
|
color: DefaultStyle.mainPageTitleColor
|
||||||
|
text: qsTr("Transfert d'appel")
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contentItem: StackLayout {
|
||||||
|
currentIndex: rightPanel.currentIndex
|
||||||
|
ContactsList {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
sideMargin: 10
|
||||||
|
topMargin: 15
|
||||||
|
groupCallVisible: false
|
||||||
|
searchBarColor: DefaultStyle.grey_0
|
||||||
|
searchBarBorderColor: DefaultStyle.callRightPanelSearchBarBorderColor
|
||||||
|
onCallButtonPressed: (address) => {
|
||||||
|
mainWindow.call.core.lTransferCall(address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GridLayout {
|
||||||
|
id: bottomButtonsLayout
|
||||||
|
rows: 1
|
||||||
|
columns: 3
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
layoutDirection: Qt.LeftToRight
|
||||||
|
columnSpacing: 20
|
||||||
|
Connections {
|
||||||
|
target: mainWindow
|
||||||
|
onCallStateChanged: if (mainWindow.callState === LinphoneEnums.CallState.Connected || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning) {
|
||||||
|
bottomButtonsLayout.layoutDirection = Qt.RightToLeft
|
||||||
|
connectedCallButtons.visible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function setButtonsEnabled(enabled) {
|
||||||
|
for(var i=0; i < children.length; ++i) {
|
||||||
|
children[i].enabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BottomButton {
|
||||||
|
Layout.row: 0
|
||||||
|
enabledIcon: AppIcons.endCall
|
||||||
|
checkable: false
|
||||||
|
Layout.column: mainWindow.callState == LinphoneEnums.CallState.OutgoingInit
|
||||||
|
|| mainWindow.callState == LinphoneEnums.CallState.OutgoingProgress
|
||||||
|
|| mainWindow.callState == LinphoneEnums.CallState.OutgoingRinging
|
||||||
|
|| mainWindow.callState == LinphoneEnums.CallState.OutgoingEarlyMedia
|
||||||
|
|| mainWindow.callState == LinphoneEnums.CallState.IncomingReceived
|
||||||
|
? 0 : bottomButtonsLayout.columns - 1
|
||||||
|
Layout.preferredWidth: 75 * DefaultStyle.dp
|
||||||
|
Layout.preferredHeight: 55 * DefaultStyle.dp
|
||||||
|
background: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: DefaultStyle.danger_500
|
||||||
|
radius: 71 * DefaultStyle.dp
|
||||||
|
}
|
||||||
|
onClicked: mainWindow.endCall()
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
id: connectedCallButtons
|
||||||
|
visible: false
|
||||||
|
Layout.row: 0
|
||||||
|
Layout.column: 1
|
||||||
|
BottomButton {
|
||||||
|
Layout.preferredWidth: 55 * DefaultStyle.dp
|
||||||
|
Layout.preferredHeight: 55 * DefaultStyle.dp
|
||||||
|
background: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: 71 * DefaultStyle.dp
|
||||||
|
color: parent.enabled
|
||||||
|
? parent.checked
|
||||||
|
? DefaultStyle.success_500main
|
||||||
|
: parent.pressed
|
||||||
|
? DefaultStyle.main2_400
|
||||||
|
: DefaultStyle.grey_500
|
||||||
|
: DefaultStyle.grey_600
|
||||||
|
}
|
||||||
|
enabled: mainWindow.callState != LinphoneEnums.CallState.PausedByRemote
|
||||||
|
enabledIcon: enabled && checked ? AppIcons.play : AppIcons.pause
|
||||||
|
checked: mainWindow.call && (mainWindow.call.callState === LinphoneEnums.CallState.Paused
|
||||||
|
|| mainWindow.call.callState === LinphoneEnums.CallState.PausedByRemote) || false
|
||||||
|
onClicked: mainWindow.call.core.lSetPaused(!mainWindow.call.core.paused)
|
||||||
|
}
|
||||||
|
BottomButton {
|
||||||
|
id: transferCallButton
|
||||||
|
enabledIcon: AppIcons.transferCall
|
||||||
|
Layout.preferredWidth: 55 * DefaultStyle.dp
|
||||||
|
Layout.preferredHeight: 55 * DefaultStyle.dp
|
||||||
|
onClicked: {
|
||||||
|
rightPanel.visible = !rightPanel.visible
|
||||||
|
rightPanel.currentIndex = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
Layout.row: 0
|
||||||
|
Layout.column: mainWindow.callState == LinphoneEnums.CallState.OutgoingInit
|
||||||
|
|| mainWindow.callState == LinphoneEnums.CallState.OutgoingProgress
|
||||||
|
|| mainWindow.callState == LinphoneEnums.CallState.OutgoingRinging
|
||||||
|
|| mainWindow.callState == LinphoneEnums.CallState.OutgoingEarlyMedia
|
||||||
|
|| mainWindow.callState == LinphoneEnums.CallState.IncomingReceived
|
||||||
|
? bottomButtonsLayout.columns - 1 : 0
|
||||||
|
BottomButton {
|
||||||
|
enabled: false
|
||||||
|
enabledIcon: AppIcons.videoCamera
|
||||||
|
disabledIcon: AppIcons.videoCameraSlash
|
||||||
|
checked: !mainWindow.call.core.cameraEnabled
|
||||||
|
Layout.preferredWidth: 55 * DefaultStyle.dp
|
||||||
|
Layout.preferredHeight: 55 * DefaultStyle.dp
|
||||||
|
onClicked: mainWindow.call.core.lSetCameraEnabled(!mainWindow.call.core.cameraEnabled)
|
||||||
|
|
||||||
|
}
|
||||||
|
BottomButton {
|
||||||
|
id: micButton
|
||||||
|
enabledIcon: AppIcons.microphone
|
||||||
|
disabledIcon: AppIcons.microphoneSlash
|
||||||
|
checked: mainWindow.call.core.microphoneMuted
|
||||||
|
Layout.preferredWidth: 55 * DefaultStyle.dp
|
||||||
|
Layout.preferredHeight: 55 * DefaultStyle.dp
|
||||||
|
onClicked: mainWindow.call.core.lSetMicrophoneMuted(!mainWindow.call.core.microphoneMuted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,7 @@ import Linphone
|
||||||
Window {
|
Window {
|
||||||
id: mainWindow
|
id: mainWindow
|
||||||
width: 1512 * DefaultStyle.dp
|
width: 1512 * DefaultStyle.dp
|
||||||
height: 930 * DefaultStyle.dp
|
height: 982 * DefaultStyle.dp
|
||||||
visible: true
|
visible: true
|
||||||
title: qsTr("Linphone")
|
title: qsTr("Linphone")
|
||||||
property bool firstConnection: true
|
property bool firstConnection: true
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,21 @@
|
||||||
|
|
||||||
list(APPEND _LINPHONEAPP_QML_FILES
|
list(APPEND _LINPHONEAPP_QML_FILES
|
||||||
view/App/Main.qml
|
view/App/Main.qml
|
||||||
|
view/App/CallsWindow.qml
|
||||||
view/App/Layout/LoginLayout.qml
|
view/App/Layout/LoginLayout.qml
|
||||||
view/App/Layout/MainLayout.qml
|
view/App/Layout/MainLayout.qml
|
||||||
|
|
||||||
view/Item/Account/Accounts.qml
|
view/Item/Account/Accounts.qml
|
||||||
|
|
||||||
|
view/Item/Call/ContactsList.qml
|
||||||
|
view/Item/Call/OngoingCallRightPanel.qml
|
||||||
|
|
||||||
|
view/Item/Notification/Notification.qml
|
||||||
|
view/Item/Notification/NotificationReceivedCall.qml
|
||||||
|
|
||||||
|
view/Item/Prototype/CanvasCircle.qml
|
||||||
|
|
||||||
|
view/Item/BusyIndicator.qml
|
||||||
view/Item/Button.qml
|
view/Item/Button.qml
|
||||||
view/Item/Carousel.qml
|
view/Item/Carousel.qml
|
||||||
view/Item/CheckBox.qml
|
view/Item/CheckBox.qml
|
||||||
|
|
@ -17,10 +27,6 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
||||||
|
|
||||||
view/Item/DesktopPopup.qml
|
view/Item/DesktopPopup.qml
|
||||||
view/Item/DigitInput.qml
|
view/Item/DigitInput.qml
|
||||||
|
|
||||||
view/Item/Notification/Notification.qml
|
|
||||||
view/Item/Notification/NotificationReceivedCall.qml
|
|
||||||
|
|
||||||
view/Item/EffectImage.qml
|
view/Item/EffectImage.qml
|
||||||
view/Item/NumericPad.qml
|
view/Item/NumericPad.qml
|
||||||
view/Item/PhoneNumberComboBox.qml
|
view/Item/PhoneNumberComboBox.qml
|
||||||
|
|
@ -48,7 +54,6 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
||||||
|
|
||||||
view/Page/Main/AbstractMainPage.qml
|
view/Page/Main/AbstractMainPage.qml
|
||||||
view/Page/Main/CallPage.qml
|
view/Page/Main/CallPage.qml
|
||||||
# view/Page/Main/OngoingCallPage.qml
|
|
||||||
|
|
||||||
# Prototypes
|
# Prototypes
|
||||||
view/Prototype/PhoneNumberPrototype.qml
|
view/Prototype/PhoneNumberPrototype.qml
|
||||||
|
|
|
||||||
22
Linphone/view/Item/BusyIndicator.qml
Normal file
22
Linphone/view/Item/BusyIndicator.qml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.2 as Control
|
||||||
|
import QtQuick.Effects
|
||||||
|
|
||||||
|
import Linphone
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: mainItem
|
||||||
|
property color indicatorColor: DefaultStyle.main1_500_main
|
||||||
|
width: busyIndicator.width
|
||||||
|
height: busyIndicator.height
|
||||||
|
Control.BusyIndicator {
|
||||||
|
id: busyIndicator
|
||||||
|
running: mainItem.visible
|
||||||
|
}
|
||||||
|
MultiEffect {
|
||||||
|
source: busyIndicator
|
||||||
|
anchors.fill: busyIndicator
|
||||||
|
colorizationColor: mainItem.indicatorColor
|
||||||
|
colorization: 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,12 +19,12 @@ Control.Button {
|
||||||
color: inversedColors
|
color: inversedColors
|
||||||
? mainItem.pressed
|
? mainItem.pressed
|
||||||
? DefaultStyle.buttonPressedInversedBackground
|
? DefaultStyle.buttonPressedInversedBackground
|
||||||
: DefaultStyle.buttonInversedBackground
|
: DefaultStyle.grey_0
|
||||||
: mainItem.pressed
|
: mainItem.pressed
|
||||||
? DefaultStyle.buttonPressedBackground
|
? DefaultStyle.buttonPressedBackground
|
||||||
: DefaultStyle.buttonBackground
|
: DefaultStyle.main1_500_main
|
||||||
radius: 24
|
radius: 24
|
||||||
border.color: inversedColors ? DefaultStyle.buttonBackground : DefaultStyle.buttonInversedBackground
|
border.color: inversedColors ? DefaultStyle.main1_500_main : DefaultStyle.grey_0
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
@ -42,17 +42,12 @@ Control.Button {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
leftPadding: 13
|
|
||||||
rightPadding: 13
|
|
||||||
topPadding: 10
|
|
||||||
bottomPadding: 10
|
|
||||||
|
|
||||||
contentItem: Text {
|
contentItem: Text {
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
text: mainItem.text
|
text: mainItem.text
|
||||||
color: inversedColors ? DefaultStyle.buttonInversedTextColor : DefaultStyle.buttonTextColor
|
color: inversedColors ? DefaultStyle.main1_500_main : DefaultStyle.grey_0
|
||||||
font {
|
font {
|
||||||
bold: mainItem.boldText
|
bold: mainItem.boldText
|
||||||
pointSize: mainItem.textSize
|
pointSize: mainItem.textSize
|
||||||
|
|
|
||||||
168
Linphone/view/Item/Call/ContactsList.qml
Normal file
168
Linphone/view/Item/Call/ContactsList.qml
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import QtQuick.Controls 2.2 as Control
|
||||||
|
import QtQuick.Effects
|
||||||
|
|
||||||
|
import Linphone
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: mainItem
|
||||||
|
property int sideMargin: 25
|
||||||
|
property int topMargin: 5
|
||||||
|
property bool groupCallVisible
|
||||||
|
property color searchBarColor: DefaultStyle.contactListSearchBarColor
|
||||||
|
property color searchBarBorderColor: "transparent"
|
||||||
|
signal callButtonPressed(string address)
|
||||||
|
clip: true
|
||||||
|
Control.Control {
|
||||||
|
id: listLayout
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: mainItem.sideMargin
|
||||||
|
anchors.rightMargin: mainItem.sideMargin
|
||||||
|
anchors.topMargin: mainItem.topMargin
|
||||||
|
background: Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: 10
|
||||||
|
SearchBar {
|
||||||
|
id: searchBar
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.maximumWidth: mainItem.width
|
||||||
|
color: mainItem.searchBarColor
|
||||||
|
borderColor: mainItem.searchBarBorderColor
|
||||||
|
placeholderText: qsTr("Rechercher un contact")
|
||||||
|
numericPad: numPad
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
visible: mainItem.groupCallVisible
|
||||||
|
Layout.fillWidth: true
|
||||||
|
leftPadding: 0
|
||||||
|
topPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
bottomPadding: 0
|
||||||
|
background: Rectangle {
|
||||||
|
color: DefaultStyle.groupCallButtonColor
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: 50
|
||||||
|
}
|
||||||
|
contentItem: RowLayout {
|
||||||
|
Image {
|
||||||
|
source: AppIcons.groupCall
|
||||||
|
Layout.preferredWidth: 35
|
||||||
|
sourceSize.width: 35
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: "Appel de groupe"
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
Image {
|
||||||
|
source: AppIcons.rightArrow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
visible: searchBar.text.length > 0 // && contactList.count === 0 (pas trouvé dans la liste)
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Text {
|
||||||
|
text: searchBar.text
|
||||||
|
maximumLineCount: 1
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
Control.Button {
|
||||||
|
implicitWidth: 30
|
||||||
|
implicitHeight: 30
|
||||||
|
background: Item {
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
contentItem: Image {
|
||||||
|
source: AppIcons.phone
|
||||||
|
width: 20
|
||||||
|
sourceSize.width: 20
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
mainItem.callButtonPressed(searchBar.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ColumnLayout {
|
||||||
|
ListView {
|
||||||
|
id: contactList
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
// call history
|
||||||
|
model: 30
|
||||||
|
delegate: Item {
|
||||||
|
required property int index
|
||||||
|
width:contactList.width
|
||||||
|
height: 30
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
Image {
|
||||||
|
source: AppIcons.info
|
||||||
|
}
|
||||||
|
ColumnLayout {
|
||||||
|
Text {
|
||||||
|
text: "John Doe"
|
||||||
|
}
|
||||||
|
// RowLayout {
|
||||||
|
// Image {
|
||||||
|
// source: AppIcons.incomingCall
|
||||||
|
// }
|
||||||
|
// Text {
|
||||||
|
// text: "info sur l'appel"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
hoverEnabled: true
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
opacity: 0.1
|
||||||
|
radius: 15
|
||||||
|
color: DefaultStyle.comboBoxHoverColor
|
||||||
|
visible: parent.containsMouse
|
||||||
|
}
|
||||||
|
onClicked: contactList.currentIndex = parent.index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
height: numPad.height
|
||||||
|
NumericPad {
|
||||||
|
id: numPad
|
||||||
|
// anchors.centerIn: parent
|
||||||
|
width: parent.width
|
||||||
|
onLaunchCall: {
|
||||||
|
var callVarObject = UtilsCpp.createCall(searchBar.text + "@sip.linphone.org")
|
||||||
|
// TODO : auto completion instead of sip linphone
|
||||||
|
var windowComp = Qt.createComponent("OngoingCallPage.qml")
|
||||||
|
var callWindow = windowComp.createObject({callVarObject: callVarObject})
|
||||||
|
callWindow.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
Linphone/view/Item/Call/OngoingCallRightPanel.qml
Normal file
61
Linphone/view/Item/Call/OngoingCallRightPanel.qml
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls as Control
|
||||||
|
import Linphone
|
||||||
|
|
||||||
|
Control.Page {
|
||||||
|
id: mainItem
|
||||||
|
property alias headerContent: header.children
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
width: mainItem.width
|
||||||
|
height: mainItem.height
|
||||||
|
color: DefaultStyle.callRightPanelBackgroundColor
|
||||||
|
radius: 15
|
||||||
|
}
|
||||||
|
|
||||||
|
header: Control.Control {
|
||||||
|
id: pageHeader
|
||||||
|
width: mainItem.width
|
||||||
|
background: Rectangle {
|
||||||
|
id: headerBackground
|
||||||
|
width: pageHeader.width
|
||||||
|
height: pageHeader.height
|
||||||
|
color: DefaultStyle.grey_0
|
||||||
|
radius: 15
|
||||||
|
Rectangle {
|
||||||
|
y: pageHeader.height/2
|
||||||
|
height: pageHeader.height/2
|
||||||
|
width: pageHeader.width
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contentItem: RowLayout {
|
||||||
|
width: pageHeader.width
|
||||||
|
height: pageHeader.height
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
anchors.left: pageHeader.left
|
||||||
|
Item {
|
||||||
|
id: header
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
id: closeButton
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
background: Item {
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
contentItem: Image {
|
||||||
|
anchors.centerIn: closeButton
|
||||||
|
source: AppIcons.closeX
|
||||||
|
width: 10
|
||||||
|
sourceSize.width: 10
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
}
|
||||||
|
onClicked: mainItem.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -91,7 +91,7 @@ ColumnLayout {
|
||||||
signal buttonClicked(int index)
|
signal buttonClicked(int index)
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: stackLayout.currentIndex == slideIndex ? DefaultStyle.buttonBackground : DefaultStyle.carouselLightGrayColor
|
color: stackLayout.currentIndex == slideIndex ? DefaultStyle.main1_500_main : DefaultStyle.carouselLightGrayColor
|
||||||
radius: 15
|
radius: 15
|
||||||
width: stackLayout.currentIndex == slideIndex ? 11 : 8
|
width: stackLayout.currentIndex == slideIndex ? 11 : 8
|
||||||
height: 8
|
height: 8
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,15 @@ Control.CheckBox {
|
||||||
x: (parent.width - width) / 2
|
x: (parent.width - width) / 2
|
||||||
y: (parent.height - height) / 2
|
y: (parent.height - height) / 2
|
||||||
radius: 3
|
radius: 3
|
||||||
border.color: DefaultStyle.checkboxBorderColor
|
border.color: DefaultStyle.main1_500_main
|
||||||
border.width: DefaultStyle.checkboxBorderWidth
|
border.width: DefaultStyle.checkboxBorderWidth
|
||||||
// color: mainItem.checked ? DefaultStyle.checkboxBorderColor : "transparent"
|
// color: mainItem.checked ? DefaultStyle.main1_500_main : "transparent"
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
visible: mainItem.checked
|
visible: mainItem.checked
|
||||||
text: "\u2714"
|
text: "\u2714"
|
||||||
font.pointSize: 18
|
font.pointSize: 18
|
||||||
color: DefaultStyle.checkboxBorderColor
|
color: DefaultStyle.main1_500_main
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ ColumnLayout {
|
||||||
visible: label.length > 0
|
visible: label.length > 0
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
text: mainItem.label
|
text: mainItem.label
|
||||||
color: combobox.activeFocus ? DefaultStyle.formItemFocusBorderColor : DefaultStyle.formItemLabelColor
|
color: combobox.activeFocus ? DefaultStyle.main1_500_main : DefaultStyle.formItemLabelColor
|
||||||
font {
|
font {
|
||||||
pointSize: DefaultStyle.formItemLabelSize
|
pointSize: DefaultStyle.formItemLabelSize
|
||||||
bold: true
|
bold: true
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import Linphone
|
||||||
Control.TextField {
|
Control.TextField {
|
||||||
id: mainItem
|
id: mainItem
|
||||||
property int inputSize: 60
|
property int inputSize: 60
|
||||||
color: activeFocus ? DefaultStyle.digitInputFocusedColor : DefaultStyle.digitInputColor
|
color: activeFocus ? DefaultStyle.main1_500_main : DefaultStyle.digitInputColor
|
||||||
rightPadding: inputSize / 4
|
rightPadding: inputSize / 4
|
||||||
leftPadding: inputSize / 4
|
leftPadding: inputSize / 4
|
||||||
validator: IntValidator{bottom: 0; top: 9}
|
validator: IntValidator{bottom: 0; top: 9}
|
||||||
|
|
@ -20,7 +20,7 @@ Control.TextField {
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
// id: background
|
// id: background
|
||||||
border.color: mainItem.activeFocus ? DefaultStyle.digitInputFocusedColor : DefaultStyle.digitInputColor
|
border.color: mainItem.activeFocus ? DefaultStyle.main1_500_main : DefaultStyle.digitInputColor
|
||||||
radius: mainItem.inputSize / 8
|
radius: mainItem.inputSize / 8
|
||||||
}
|
}
|
||||||
// cursorDelegate: Rectangle {
|
// cursorDelegate: Rectangle {
|
||||||
|
|
@ -34,6 +34,6 @@ Control.TextField {
|
||||||
// // anchors.left: parent.left
|
// // anchors.left: parent.left
|
||||||
// // anchors.bottomMargin: inputSize/8
|
// // anchors.bottomMargin: inputSize/8
|
||||||
// // transform: [/*Translate {x: mainItem.cursorRectangle.height},*/ Rotation {angle: -90}]
|
// // transform: [/*Translate {x: mainItem.cursorRectangle.height},*/ Rotation {angle: -90}]
|
||||||
// color:DefaultStyle.digitInputFocusedColor
|
// color:DefaultStyle.main1_500_main
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,19 +17,20 @@ Item {
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: image
|
id: image
|
||||||
|
visible: !effect2.enabled
|
||||||
|
sourceSize.width: parent.width
|
||||||
|
sourceSize.height: parent.height
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height
|
height: parent.height
|
||||||
//sourceSize.width: parent.width
|
|
||||||
fillMode: Image.PreserveAspectFit
|
fillMode: Image.PreserveAspectFit
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
visible: !effect2.enabled
|
|
||||||
}
|
}
|
||||||
MultiEffect {
|
MultiEffect {
|
||||||
id: effect
|
id: effect
|
||||||
|
visible: !effect2.enabled
|
||||||
anchors.fill: image
|
anchors.fill: image
|
||||||
source: image
|
source: image
|
||||||
maskSource: image
|
maskSource: image
|
||||||
visible: !effect2.enabled
|
|
||||||
brightness: effect2.enabled ? 1.0 : 0.0
|
brightness: effect2.enabled ? 1.0 : 0.0
|
||||||
}
|
}
|
||||||
MultiEffect {
|
MultiEffect {
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ ColumnLayout {
|
||||||
text: "Forgotten password?"
|
text: "Forgotten password?"
|
||||||
font{
|
font{
|
||||||
underline: true
|
underline: true
|
||||||
pointSize: DefaultStyle.defaultTextSize
|
pointSize: DefaultStyle.indicatorMessageTextSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onClicked: console.debug("[LoginForm]User: forgotten password button clicked")
|
onClicked: console.debug("[LoginForm]User: forgotten password button clicked")
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,10 @@ Notification {
|
||||||
Layout.rightMargin: 20
|
Layout.rightMargin: 20
|
||||||
onClicked: {
|
onClicked: {
|
||||||
notification.call.core.lAccept(true)
|
notification.call.core.lAccept(true)
|
||||||
|
var windowComp = Qt.createComponent("OngoingCallPage.qml")
|
||||||
|
var callWindow = windowComp.createObject(null, {callVarObject: callVarObject})
|
||||||
|
callWindow.modality = Qt.ApplicationModal
|
||||||
|
callWindow.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item{
|
Item{
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ Control.Popup {
|
||||||
clip: true
|
clip: true
|
||||||
id: mainItem
|
id: mainItem
|
||||||
signal buttonPressed(string text)
|
signal buttonPressed(string text)
|
||||||
|
signal launchCall()
|
||||||
signal wipe()
|
signal wipe()
|
||||||
closePolicy: Control.Popup.CloseOnEscape
|
closePolicy: Control.Popup.CloseOnEscape
|
||||||
leftPadding: closeButton.width
|
leftPadding: closeButton.width
|
||||||
|
|
@ -61,7 +62,7 @@ Control.Popup {
|
||||||
implicitHeight: 40
|
implicitHeight: 40
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: numPadButton.down ? DefaultStyle.numericPadPressedButtonColor : DefaultStyle.numericPadButtonColor
|
color: numPadButton.down ? DefaultStyle.numericPadPressedButtonColor : DefaultStyle.grey_0
|
||||||
radius: 20
|
radius: 20
|
||||||
}
|
}
|
||||||
contentItem: Text {
|
contentItem: Text {
|
||||||
|
|
@ -91,7 +92,7 @@ Control.Popup {
|
||||||
implicitHeight: 40
|
implicitHeight: 40
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: digitButton.down ? DefaultStyle.numericPadPressedButtonColor : DefaultStyle.numericPadButtonColor
|
color: digitButton.down ? DefaultStyle.numericPadPressedButtonColor : DefaultStyle.grey_0
|
||||||
radius: 20
|
radius: 20
|
||||||
}
|
}
|
||||||
contentItem: Item {
|
contentItem: Item {
|
||||||
|
|
@ -131,7 +132,7 @@ Control.Popup {
|
||||||
bottomPadding: 15
|
bottomPadding: 15
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: DefaultStyle.numericPadLaunchCallButtonColor
|
color: DefaultStyle.launchCallButtonColor
|
||||||
radius: 15
|
radius: 15
|
||||||
}
|
}
|
||||||
contentItem: EffectImage {
|
contentItem: EffectImage {
|
||||||
|
|
@ -142,8 +143,9 @@ Control.Popup {
|
||||||
width: 20
|
width: 20
|
||||||
height: 20
|
height: 20
|
||||||
image.fillMode: Image.PreserveAspectFit
|
image.fillMode: Image.PreserveAspectFit
|
||||||
effect.brightness: 1.0
|
colorizationColor: DefaultStyle.grey_0
|
||||||
}
|
}
|
||||||
|
onClicked: mainItem.launchCall()
|
||||||
}
|
}
|
||||||
Button {
|
Button {
|
||||||
leftPadding: 5
|
leftPadding: 5
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ ColumnLayout {
|
||||||
visible: mainItem.label.length > 0
|
visible: mainItem.label.length > 0
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
text: mainItem.label
|
text: mainItem.label
|
||||||
color: combobox.activeFocus ? DefaultStyle.formItemFocusBorderColor : DefaultStyle.formItemLabelColor
|
color: combobox.activeFocus ? DefaultStyle.main1_500_main : DefaultStyle.formItemLabelColor
|
||||||
font {
|
font {
|
||||||
pointSize: DefaultStyle.formItemLabelSize
|
pointSize: DefaultStyle.formItemLabelSize
|
||||||
bold: true
|
bold: true
|
||||||
|
|
@ -39,7 +39,7 @@ ColumnLayout {
|
||||||
? (mainItem.errorMessage.length > 0
|
? (mainItem.errorMessage.length > 0
|
||||||
? DefaultStyle.errorMessageColor
|
? DefaultStyle.errorMessageColor
|
||||||
: textField.activeFocus
|
: textField.activeFocus
|
||||||
? DefaultStyle.formItemFocusBorderColor
|
? DefaultStyle.main1_500_main
|
||||||
: DefaultStyle.formItemBorderColor)
|
: DefaultStyle.formItemBorderColor)
|
||||||
: "transparent"
|
: "transparent"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ ColumnLayout {
|
||||||
visible: label.length > 0
|
visible: label.length > 0
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
text: mainItem.label + (mainItem.mandatory ? "*" : "")
|
text: mainItem.label + (mainItem.mandatory ? "*" : "")
|
||||||
color: (combobox.hasActiveFocus || textField.hasActiveFocus) ? DefaultStyle.formItemFocusBorderColor : DefaultStyle.formItemLabelColor
|
color: (combobox.hasActiveFocus || textField.hasActiveFocus) ? DefaultStyle.main1_500_main : DefaultStyle.formItemLabelColor
|
||||||
font {
|
font {
|
||||||
pointSize: DefaultStyle.formItemLabelSize
|
pointSize: DefaultStyle.formItemLabelSize
|
||||||
bold: true
|
bold: true
|
||||||
|
|
@ -34,7 +34,7 @@ ColumnLayout {
|
||||||
border.color: mainItem.errorMessage.length > 0
|
border.color: mainItem.errorMessage.length > 0
|
||||||
? DefaultStyle.errorMessageColor
|
? DefaultStyle.errorMessageColor
|
||||||
: (textField.hasActiveFocus || combobox.hasActiveFocus)
|
: (textField.hasActiveFocus || combobox.hasActiveFocus)
|
||||||
? DefaultStyle.formItemFocusBorderColor
|
? DefaultStyle.main1_500_main
|
||||||
: DefaultStyle.formItemBorderColor
|
: DefaultStyle.formItemBorderColor
|
||||||
RowLayout {
|
RowLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
@ -69,7 +69,7 @@ ColumnLayout {
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
font {
|
font {
|
||||||
pointSize: DefaultStyle.defaultTextSize
|
pointSize: DefaultStyle.indicatorMessageTextSize
|
||||||
family: DefaultStyle.defaultFont
|
family: DefaultStyle.defaultFont
|
||||||
bold: true
|
bold: true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
61
Linphone/view/Item/Prototype/CanvasCircle.qml
Normal file
61
Linphone/view/Item/Prototype/CanvasCircle.qml
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
property int size: 150
|
||||||
|
property color borderColor
|
||||||
|
property color innerColor
|
||||||
|
width: size
|
||||||
|
height: size
|
||||||
|
|
||||||
|
onBorderColorChanged: c.requestPaint()
|
||||||
|
|
||||||
|
function requestPaint(animated) {
|
||||||
|
c.animated = animated
|
||||||
|
if (animated) animationTimer.restart()
|
||||||
|
else {
|
||||||
|
animationTimer.stop()
|
||||||
|
c.requestPaint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Canvas {
|
||||||
|
id: c
|
||||||
|
property bool animated: false
|
||||||
|
property int offset: 0
|
||||||
|
anchors.fill: parent
|
||||||
|
antialiasing: true
|
||||||
|
onOffsetChanged: requestPaint()
|
||||||
|
Timer {
|
||||||
|
id: animationTimer
|
||||||
|
interval: 200
|
||||||
|
repeat: true
|
||||||
|
onTriggered: c.offset = (c.offset + 1)%360
|
||||||
|
}
|
||||||
|
|
||||||
|
onPaint: {
|
||||||
|
var ctx = getContext("2d");
|
||||||
|
ctx.reset()
|
||||||
|
ctx.setLineDash([3, 2]);
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
|
||||||
|
ctx.lineDashOffset = offset;
|
||||||
|
|
||||||
|
var x = root.width / 2;
|
||||||
|
var y = root.height / 2;
|
||||||
|
|
||||||
|
var radius = root.size / 2
|
||||||
|
var startAngle = (Math.PI / 180) * 270;
|
||||||
|
var fullAngle = (Math.PI / 180) * (270 + 360);
|
||||||
|
|
||||||
|
ctx.strokeStyle = root.borderColor;
|
||||||
|
ctx.fillStyle = root.innerColor;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(x, y, radius - 1, 0, 2 * Math.PI);
|
||||||
|
ctx.fill();
|
||||||
|
if (animated) {
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,7 +20,7 @@ Control.RadioButton {
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: DefaultStyle.formItemBackgroundColor
|
color: DefaultStyle.formItemBackgroundColor
|
||||||
border.color: mainItem.checked ? DefaultStyle.radioButtonCheckedColor : "transparent"
|
border.color: mainItem.checked ? DefaultStyle.info_500_main : "transparent"
|
||||||
radius: 20
|
radius: 20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ Control.RadioButton {
|
||||||
implicitWidth: 16
|
implicitWidth: 16
|
||||||
implicitHeight: 16
|
implicitHeight: 16
|
||||||
radius: implicitWidth/2
|
radius: implicitWidth/2
|
||||||
border.color: mainItem.checked ? DefaultStyle.radioButtonCheckedColor : DefaultStyle.radioButtonUncheckedColor
|
border.color: mainItem.checked ? DefaultStyle.info_500_main : DefaultStyle.main1_500_main
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: parent.width/2
|
width: parent.width/2
|
||||||
|
|
@ -42,14 +42,14 @@ Control.RadioButton {
|
||||||
x: parent.width/4
|
x: parent.width/4
|
||||||
y: parent.width/4
|
y: parent.width/4
|
||||||
radius: width/2
|
radius: width/2
|
||||||
color: DefaultStyle.radioButtonCheckedColor
|
color: DefaultStyle.info_500_main
|
||||||
visible: mainItem.checked
|
visible: mainItem.checked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: mainItem.title
|
text: mainItem.title
|
||||||
font.bold: true
|
font.bold: true
|
||||||
color: DefaultStyle.radioButtonTitleColor
|
color: DefaultStyle.grey_900
|
||||||
font.pointSize: DefaultStyle.radioButtonTitleSize
|
font.pointSize: DefaultStyle.radioButtonTitleSize
|
||||||
}
|
}
|
||||||
Control.Button {
|
Control.Button {
|
||||||
|
|
@ -83,7 +83,7 @@ Control.RadioButton {
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
Layout.preferredWidth: 220
|
Layout.preferredWidth: 220
|
||||||
Layout.preferredHeight: 100
|
Layout.preferredHeight: 100
|
||||||
font.pointSize: DefaultStyle.defaultTextSize
|
font.pointSize: DefaultStyle.descriptionTextSize
|
||||||
text: mainItem.contentText
|
text: mainItem.contentText
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
import QtQuick 2.7
|
import QtQuick 2.7
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
function genRandomColor(){
|
||||||
|
return '#'+ Math.floor(Math.random()*255).toString(16)
|
||||||
|
+Math.floor(Math.random()*255).toString(16)
|
||||||
|
+Math.floor(Math.random()*255).toString(16)
|
||||||
|
}
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: "blue"
|
color: genRandomColor() //"blue"
|
||||||
opacity: 0.2
|
opacity: 0.2
|
||||||
border.color: "green"
|
border.color: genRandomColor() //"red"
|
||||||
border.width: 2
|
border.width: 2
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,12 @@ Rectangle {
|
||||||
id: mainItem
|
id: mainItem
|
||||||
property string placeholderText: ""
|
property string placeholderText: ""
|
||||||
property int textInputWidth: 350
|
property int textInputWidth: 350
|
||||||
property var validator: RegularExpressionValidator{}
|
property color borderColor: "transparent"
|
||||||
property string text: textField.text
|
property string text: textField.text
|
||||||
|
property var validator: RegularExpressionValidator{}
|
||||||
|
property var numericPad
|
||||||
property alias numericPadButton: dialerButton
|
property alias numericPadButton: dialerButton
|
||||||
readonly property bool hasActiveFocus: textField.activeFocus
|
readonly property bool hasActiveFocus: textField.activeFocus
|
||||||
property var numericPad
|
|
||||||
signal numericPadButtonPressed(bool checked)
|
signal numericPadButtonPressed(bool checked)
|
||||||
|
|
||||||
onVisibleChanged: if (!visible && numericPad) numericPad.close()
|
onVisibleChanged: if (!visible && numericPad) numericPad.close()
|
||||||
|
|
@ -32,7 +33,7 @@ Rectangle {
|
||||||
implicitHeight: 30
|
implicitHeight: 30
|
||||||
radius: 20
|
radius: 20
|
||||||
color: DefaultStyle.formItemBackgroundColor
|
color: DefaultStyle.formItemBackgroundColor
|
||||||
border.color: textField.activeFocus ? DefaultStyle.searchBarFocusBorderColor : "transparent"
|
border.color: textField.activeFocus ? DefaultStyle.searchBarFocusBorderColor : mainItem.borderColor
|
||||||
Image {
|
Image {
|
||||||
id: magnifier
|
id: magnifier
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|
@ -43,9 +44,10 @@ Rectangle {
|
||||||
Control.TextField {
|
Control.TextField {
|
||||||
id: textField
|
id: textField
|
||||||
anchors.left: magnifier.right
|
anchors.left: magnifier.right
|
||||||
anchors.right: dialerButton.visible ? dialerButton.left : parent.right
|
anchors.right: clearTextButton.left
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
placeholderText: mainItem.placeholderText
|
placeholderText: mainItem.placeholderText
|
||||||
|
width: mainItem.width - dialerButton.width
|
||||||
echoMode: (mainItem.hidden && !dialerButton.checked) ? TextInput.Password : TextInput.Normal
|
echoMode: (mainItem.hidden && !dialerButton.checked) ? TextInput.Password : TextInput.Normal
|
||||||
font.family: DefaultStyle.defaultFont
|
font.family: DefaultStyle.defaultFont
|
||||||
font.pointSize: DefaultStyle.defaultFontPointSize
|
font.pointSize: DefaultStyle.defaultFontPointSize
|
||||||
|
|
@ -57,13 +59,13 @@ Rectangle {
|
||||||
}
|
}
|
||||||
cursorDelegate: Rectangle {
|
cursorDelegate: Rectangle {
|
||||||
visible: textField.activeFocus
|
visible: textField.activeFocus
|
||||||
color: DefaultStyle.formItemFocusBorderColor
|
color: DefaultStyle.main1_500_main
|
||||||
width: 2
|
width: 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Control.Button {
|
Control.Button {
|
||||||
id: dialerButton
|
id: dialerButton
|
||||||
visible: numericPad != undefined
|
visible: numericPad != undefined && textField.text.length === 0
|
||||||
checkable: true
|
checkable: true
|
||||||
checked: false
|
checked: false
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
|
|
@ -82,4 +84,24 @@ Rectangle {
|
||||||
else mainItem.numericPad.close()
|
else mainItem.numericPad.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Control.Button {
|
||||||
|
id: clearTextButton
|
||||||
|
visible: textField.text.length > 0
|
||||||
|
checkable: true
|
||||||
|
checked: false
|
||||||
|
background: Rectangle {
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
|
contentItem: Image {
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: AppIcons.closeX
|
||||||
|
}
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 10
|
||||||
|
onCheckedChanged: {
|
||||||
|
textField.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ Control.TabBar {
|
||||||
|
|
||||||
// Quick.Rectangle {
|
// Quick.Rectangle {
|
||||||
// height: 4
|
// height: 4
|
||||||
// color: DefaultStyle.orangeColor
|
// color: DefaultStyle.main1_500_main
|
||||||
// anchors.bottom: parent.bottom
|
// anchors.bottom: parent.bottom
|
||||||
// // anchors.left: mainItem.currentItem.left
|
// // anchors.left: mainItem.currentItem.left
|
||||||
// // anchors.right: mainItem.currentItem.right
|
// // anchors.right: mainItem.currentItem.right
|
||||||
|
|
@ -59,7 +59,7 @@ Control.TabBar {
|
||||||
Quick.Rectangle {
|
Quick.Rectangle {
|
||||||
visible: mainItem.currentIndex === index
|
visible: mainItem.currentIndex === index
|
||||||
height: 4
|
height: 4
|
||||||
color: DefaultStyle.orangeColor
|
color: DefaultStyle.main1_500_main
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ ColumnLayout {
|
||||||
visible: mainItem.label.length > 0
|
visible: mainItem.label.length > 0
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
text: mainItem.label + (mainItem.mandatory ? "*" : "")
|
text: mainItem.label + (mainItem.mandatory ? "*" : "")
|
||||||
color: textField.activeFocus ? DefaultStyle.formItemFocusBorderColor : DefaultStyle.formItemLabelColor
|
color: textField.activeFocus ? DefaultStyle.main1_500_main : DefaultStyle.formItemLabelColor
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
|
|
@ -58,7 +58,7 @@ ColumnLayout {
|
||||||
? (mainItem.errorMessage.length > 0
|
? (mainItem.errorMessage.length > 0
|
||||||
? DefaultStyle.errorMessageColor
|
? DefaultStyle.errorMessageColor
|
||||||
: textField.activeFocus
|
: textField.activeFocus
|
||||||
? DefaultStyle.formItemFocusBorderColor
|
? DefaultStyle.main1_500_main
|
||||||
: DefaultStyle.formItemBorderColor)
|
: DefaultStyle.formItemBorderColor)
|
||||||
: "transparent"
|
: "transparent"
|
||||||
Control.TextField {
|
Control.TextField {
|
||||||
|
|
@ -78,7 +78,7 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
cursorDelegate: Rectangle {
|
cursorDelegate: Rectangle {
|
||||||
visible: textField.activeFocus
|
visible: textField.activeFocus
|
||||||
color: DefaultStyle.formItemFocusBorderColor
|
color: DefaultStyle.main1_500_main
|
||||||
width: 2
|
width: 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +107,7 @@ ColumnLayout {
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
// maximumLineCount: 1
|
// maximumLineCount: 1
|
||||||
font {
|
font {
|
||||||
pointSize: DefaultStyle.defaultTextSize
|
pointSize: DefaultStyle.indicatorMessageTextSize
|
||||||
family: DefaultStyle.defaultFont
|
family: DefaultStyle.defaultFont
|
||||||
bold: true
|
bold: true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,18 +33,18 @@ Control.TabBar {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: DefaultStyle.verticalTabBarColor
|
color: DefaultStyle.main1_500_main
|
||||||
radius: 25
|
radius: 25
|
||||||
}
|
}
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: DefaultStyle.verticalTabBarColor
|
color: DefaultStyle.main1_500_main
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
width: parent.width/2
|
width: parent.width/2
|
||||||
height: parent.height/2
|
height: parent.height/2
|
||||||
}
|
}
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: DefaultStyle.verticalTabBarColor
|
color: DefaultStyle.main1_500_main
|
||||||
x: parent.x + parent.width/2
|
x: parent.x + parent.width/2
|
||||||
y: parent.y + parent.height/2
|
y: parent.y + parent.height/2
|
||||||
width: parent.width/2
|
width: parent.width/2
|
||||||
|
|
@ -69,9 +69,8 @@ Control.TabBar {
|
||||||
Layout.preferredWidth: buttonSize
|
Layout.preferredWidth: buttonSize
|
||||||
Layout.preferredHeight: buttonSize
|
Layout.preferredHeight: buttonSize
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
image.sourceSize.width: buttonSize
|
|
||||||
image.fillMode: Image.PreserveAspectFit
|
image.fillMode: Image.PreserveAspectFit
|
||||||
effect.brightness: 1.0
|
colorizationColor: DefaultStyle.grey_0
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
id: buttonText
|
id: buttonText
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ LoginLayout {
|
||||||
Text {
|
Text {
|
||||||
Layout.rightMargin: 15
|
Layout.rightMargin: 15
|
||||||
text: "No account yet ?"
|
text: "No account yet ?"
|
||||||
font.pointSize: DefaultStyle.defaultTextSize
|
font.pointSize: DefaultStyle.indicatorMessageTextSize
|
||||||
}
|
}
|
||||||
Button {
|
Button {
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ LoginLayout {
|
||||||
Layout.rightMargin: 15
|
Layout.rightMargin: 15
|
||||||
text: "Didn't receive the code ?"
|
text: "Didn't receive the code ?"
|
||||||
color: DefaultStyle.questionTextColor
|
color: DefaultStyle.questionTextColor
|
||||||
font.pointSize: DefaultStyle.defaultTextSize
|
font.pointSize: DefaultStyle.indicatorMessageTextSize
|
||||||
}
|
}
|
||||||
Button {
|
Button {
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ LoginLayout {
|
||||||
Layout.rightMargin: 15
|
Layout.rightMargin: 15
|
||||||
color: DefaultStyle.questionTextColor
|
color: DefaultStyle.questionTextColor
|
||||||
text: "Already have an account ?"
|
text: "Already have an account ?"
|
||||||
font.pointSize: DefaultStyle.defaultTextSize
|
font.pointSize: DefaultStyle.indicatorMessageTextSize
|
||||||
}
|
}
|
||||||
Button {
|
Button {
|
||||||
// Layout.alignment: Qt.AlignRight
|
// Layout.alignment: Qt.AlignRight
|
||||||
|
|
@ -87,7 +87,7 @@ LoginLayout {
|
||||||
Text {
|
Text {
|
||||||
text: "The password must contain 6 characters minimum"
|
text: "The password must contain 6 characters minimum"
|
||||||
font {
|
font {
|
||||||
pointSize: DefaultStyle.defaultTextSize
|
pointSize: DefaultStyle.indicatorMessageTextSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +101,7 @@ LoginLayout {
|
||||||
Text {
|
Text {
|
||||||
text: "The password must contain 6 characters minimum"
|
text: "The password must contain 6 characters minimum"
|
||||||
font {
|
font {
|
||||||
pointSize: DefaultStyle.defaultTextSize
|
pointSize: DefaultStyle.indicatorMessageTextSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -176,7 +176,7 @@ LoginLayout {
|
||||||
Text {
|
Text {
|
||||||
text: "The password must contain 6 characters minimum"
|
text: "The password must contain 6 characters minimum"
|
||||||
font {
|
font {
|
||||||
pointSize: DefaultStyle.defaultTextSize
|
pointSize: DefaultStyle.indicatorMessageTextSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -191,7 +191,7 @@ LoginLayout {
|
||||||
Text {
|
Text {
|
||||||
text: "The password must contain 6 characters minimum"
|
text: "The password must contain 6 characters minimum"
|
||||||
font {
|
font {
|
||||||
pointSize: DefaultStyle.defaultTextSize
|
pointSize: DefaultStyle.indicatorMessageTextSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ LoginLayout {
|
||||||
Text {
|
Text {
|
||||||
Layout.rightMargin: 15
|
Layout.rightMargin: 15
|
||||||
text: "No account yet ?"
|
text: "No account yet ?"
|
||||||
font.pointSize: DefaultStyle.defaultTextSize
|
font.pointSize: DefaultStyle.indicatorMessageTextSize
|
||||||
}
|
}
|
||||||
Button {
|
Button {
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
|
|
@ -75,7 +75,7 @@ LoginLayout {
|
||||||
width: rootStackView.width
|
width: rootStackView.width
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
color: DefaultStyle.darkGrayColor
|
color: DefaultStyle.darkGrayColor
|
||||||
font.pointSize: DefaultStyle.defaultTextSize
|
font.pointSize: DefaultStyle.descriptionTextSize
|
||||||
text: "<p>Some features require a Linphone account, such as group messaging, video conferences...</p>
|
text: "<p>Some features require a Linphone account, such as group messaging, video conferences...</p>
|
||||||
<p>These features are hidden when you register with a third party SIP account.</p>
|
<p>These features are hidden when you register with a third party SIP account.</p>
|
||||||
<p>To enable it in a commercial projet, please contact us. </p>"
|
<p>To enable it in a commercial projet, please contact us. </p>"
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@ Item {
|
||||||
property string newItemIconSource
|
property string newItemIconSource
|
||||||
property string emptyListText
|
property string emptyListText
|
||||||
property alias leftPanelContent: leftPanel.children
|
property alias leftPanelContent: leftPanel.children
|
||||||
property Component rightPanelContent
|
property var rightPanelContent: rightPanelItem.children
|
||||||
property bool showDefaultItem: true
|
property bool showDefaultItem: true
|
||||||
onShowDefaultItemChanged: stackView.replace(showDefaultItem ? defaultItem : rightPanel)
|
// onShowDefaultItemChanged: stackView.replace(showDefaultItem ? defaultItem : rightPanelItem)
|
||||||
signal noItemButtonPressed()
|
signal noItemButtonPressed()
|
||||||
|
|
||||||
Control.SplitView {
|
Control.SplitView {
|
||||||
|
|
@ -37,25 +37,25 @@ Item {
|
||||||
id: rightPanel
|
id: rightPanel
|
||||||
clip: true
|
clip: true
|
||||||
color: DefaultStyle.mainPageRightPanelBackgroundColor
|
color: DefaultStyle.mainPageRightPanelBackgroundColor
|
||||||
Control.StackView {
|
StackLayout {
|
||||||
id: stackView
|
currentIndex: mainItem.showDefaultItem ? 0 : 1
|
||||||
initialItem: defaultItem
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Layout.alignment: Qt.AlignCenter
|
ColumnLayout {
|
||||||
}
|
|
||||||
Component {
|
|
||||||
id: defaultItem
|
id: defaultItem
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
spacing: 25
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Item {
|
Item {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
}
|
}
|
||||||
ColumnLayout {
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.fillWidth: true
|
|
||||||
visible: mainItem.showDefaultItem
|
|
||||||
// anchors.centerIn: parent
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
spacing: 25
|
|
||||||
Image {
|
Image {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
source: AppIcons.noItemImage
|
source: AppIcons.noItemImage
|
||||||
|
|
@ -73,7 +73,7 @@ Item {
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
EffectImage {
|
EffectImage {
|
||||||
effect.brightness: 1
|
colorizationColor: DefaultStyle.grey_0
|
||||||
image.source: mainItem.newItemIconSource
|
image.source: mainItem.newItemIconSource
|
||||||
image.width: 20
|
image.width: 20
|
||||||
image.fillMode: Image.PreserveAspectFit
|
image.fillMode: Image.PreserveAspectFit
|
||||||
|
|
@ -81,7 +81,7 @@ Item {
|
||||||
Text {
|
Text {
|
||||||
text: mainItem.noItemButtonText
|
text: mainItem.noItemButtonText
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
color: DefaultStyle.buttonTextColor
|
color: DefaultStyle.grey_0
|
||||||
font {
|
font {
|
||||||
bold: true
|
bold: true
|
||||||
pointSize: DefaultStyle.buttonTextSize
|
pointSize: DefaultStyle.buttonTextSize
|
||||||
|
|
@ -91,13 +91,23 @@ Item {
|
||||||
}
|
}
|
||||||
onPressed: mainItem.noItemButtonPressed()
|
onPressed: mainItem.noItemButtonPressed()
|
||||||
}
|
}
|
||||||
|
Item {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Item {
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
id: rightPanelItem
|
||||||
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import QtQuick 2.15
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import QtQuick.Controls as Control
|
import QtQuick.Controls as Control
|
||||||
import Linphone
|
import Linphone
|
||||||
|
import UtilsCpp 1.0
|
||||||
|
|
||||||
AbstractMainPage {
|
AbstractMainPage {
|
||||||
id: mainItem
|
id: mainItem
|
||||||
|
|
@ -16,10 +17,12 @@ AbstractMainPage {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Control.StackView {
|
Control.StackView {
|
||||||
id: listStackView
|
id: listStackView
|
||||||
|
clip: true
|
||||||
initialItem: listItem
|
initialItem: listItem
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: 25
|
property int sideMargin: 25
|
||||||
anchors.rightMargin: 25
|
// anchors.leftMargin: 25
|
||||||
|
// anchors.rightMargin: 25
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
id: listItem
|
id: listItem
|
||||||
|
|
@ -27,6 +30,8 @@ AbstractMainPage {
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: listStackView.sideMargin
|
||||||
|
Layout.rightMargin: listStackView.sideMargin
|
||||||
Text {
|
Text {
|
||||||
text: qsTr("Appels")
|
text: qsTr("Appels")
|
||||||
color: DefaultStyle.mainPageTitleColor
|
color: DefaultStyle.mainPageTitleColor
|
||||||
|
|
@ -65,6 +70,8 @@ AbstractMainPage {
|
||||||
id: listLayout
|
id: listLayout
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
Layout.leftMargin: listStackView.sideMargin
|
||||||
|
Layout.rightMargin: listStackView.sideMargin
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
@ -148,6 +155,11 @@ AbstractMainPage {
|
||||||
|
|
||||||
onCountChanged: mainItem.showDefaultItem = listView.count === 0
|
onCountChanged: mainItem.showDefaultItem = listView.count === 0
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: mainItem
|
||||||
|
onShowDefaultItemChanged: mainItem.showDefaultItem = mainItem.showDefaultItem && listView.count === 0
|
||||||
|
}
|
||||||
|
|
||||||
Control.ScrollIndicator.vertical: Control.ScrollIndicator { }
|
Control.ScrollIndicator.vertical: Control.ScrollIndicator { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -158,7 +170,13 @@ AbstractMainPage {
|
||||||
Component {
|
Component {
|
||||||
id: newCallItem
|
id: newCallItem
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
Control.StackView.onActivating: {
|
||||||
|
mainItem.showDefaultItem = false
|
||||||
|
}
|
||||||
|
Control.StackView.onDeactivating: mainItem.showDefaultItem = true
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
Layout.leftMargin: listStackView.sideMargin
|
||||||
|
Layout.rightMargin: listStackView.sideMargin
|
||||||
Control.Button {
|
Control.Button {
|
||||||
background: Item {
|
background: Item {
|
||||||
}
|
}
|
||||||
|
|
@ -180,72 +198,24 @@ AbstractMainPage {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Control.Control {
|
ContactsList {
|
||||||
id: listLayout
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
background: Rectangle {
|
Layout.maximumWidth: parent.width
|
||||||
anchors.fill: parent
|
groupCallVisible: true
|
||||||
}
|
searchBarColor: DefaultStyle.contactListSearchBarColor
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
SearchBar {
|
|
||||||
id: searchBar
|
|
||||||
Layout.alignment: Qt.AlignTop
|
|
||||||
Layout.fillWidth: true
|
|
||||||
placeholderText: qsTr("Rechercher un appel")
|
|
||||||
numericPad: numPad
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
leftPadding: 0
|
|
||||||
topPadding: 0
|
|
||||||
rightPadding: 0
|
|
||||||
bottomPadding: 0
|
|
||||||
background: Rectangle {
|
|
||||||
color: DefaultStyle.groupCallButtonColor
|
|
||||||
anchors.fill: parent
|
|
||||||
radius: 50
|
|
||||||
}
|
|
||||||
contentItem: RowLayout {
|
|
||||||
Image {
|
|
||||||
source: AppIcons.groupCall
|
|
||||||
Layout.preferredWidth: 35
|
|
||||||
sourceSize.width: 35
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: "Appel de groupe"
|
|
||||||
font.bold: true
|
|
||||||
}
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
Image {
|
|
||||||
source: AppIcons.rightArrow
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ColumnLayout {
|
|
||||||
ListView {
|
|
||||||
Layout.fillHeight: true
|
|
||||||
// call history
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
onCallButtonPressed: (address) => {
|
||||||
anchors.bottom: parent.bottom
|
var addressEnd = "@sip.linphone.org"
|
||||||
anchors.left: parent.left
|
if (!address.endsWith(addressEnd)) address += addressEnd
|
||||||
anchors.right: parent.right
|
var callVarObject = UtilsCpp.createCall(address)
|
||||||
height: numPad.height
|
// var windowComp = Qt.createComponent("CallsWindow.qml")
|
||||||
NumericPad {
|
// var call = callVarObject.value
|
||||||
id: numPad
|
// var callWindow = windowComp.createObject(null, {callVarObject: callVarObject})
|
||||||
// anchors.centerIn: parent
|
// callWindow.modality = Qt.ApplicationModal
|
||||||
width: parent.width
|
// callWindow.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ QtObject {
|
||||||
property string phoneSelected: "image://internal/phone-selected.svg"
|
property string phoneSelected: "image://internal/phone-selected.svg"
|
||||||
property string newCall: "image://internal/phone-plus.svg"
|
property string newCall: "image://internal/phone-plus.svg"
|
||||||
property string endCall: "image://internal/phone-disconnect.svg"
|
property string endCall: "image://internal/phone-disconnect.svg"
|
||||||
|
property string transferCall: "image://internal/phone-transfer.svg"
|
||||||
property string adressBook: "image://internal/address-book.svg"
|
property string adressBook: "image://internal/address-book.svg"
|
||||||
property string adressBookSelected: "image://internal/address-book-selected.svg"
|
property string adressBookSelected: "image://internal/address-book-selected.svg"
|
||||||
property string chatTeardropText: "image://internal/chat-teardrop-text.svg"
|
property string chatTeardropText: "image://internal/chat-teardrop-text.svg"
|
||||||
|
|
@ -44,5 +45,15 @@ QtObject {
|
||||||
property string incomingCallRejected: "image://internal/incoming_call_rejected.svg"
|
property string incomingCallRejected: "image://internal/incoming_call_rejected.svg"
|
||||||
property string outgoingCall: "image://internal/outgoing_call.svg"
|
property string outgoingCall: "image://internal/outgoing_call.svg"
|
||||||
property string outgoingCallMissed: "image://internal/outgoing_call_missed.svg"
|
property string outgoingCallMissed: "image://internal/outgoing_call_missed.svg"
|
||||||
property string outgoingCallRejected: "image://internal/outgoing_call_rejected.svg"
|
property string microphone: "image://internal/microphone.svg"
|
||||||
|
property string microphoneSlash: "image://internal/microphone-slash.svg"
|
||||||
|
property string videoCamera: "image://internal/video-camera.svg"
|
||||||
|
property string videoCameraSlash: "image://internal/video-camera-slash.svg"
|
||||||
|
property string speaker: "image://internal/speaker-high.svg"
|
||||||
|
property string speakerSlash: "image://internal/speaker-slash.svg"
|
||||||
|
property string trusted: "image://internal/trusted.svg"
|
||||||
|
property string avatar: "image://internal/randomAvatar.png"
|
||||||
|
property string pause: "image://internal/pause.svg"
|
||||||
|
property string play: "image://internal/play.svg"
|
||||||
|
property string smiley: "image://internal/smiley.svg"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,21 +2,34 @@ pragma Singleton
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
|
property color main1_500_main: "#FE5E00"
|
||||||
|
|
||||||
|
property color main2_0: "#FAFEFF"
|
||||||
|
property color main2_100: "#EEF6F8"
|
||||||
|
property color main2_200: "#DFECF2"
|
||||||
|
property color main2_300: "#C0D1D9"
|
||||||
|
property color main2_400: "#9AABB5"
|
||||||
|
property color main2_500main: "#6C7A87"
|
||||||
|
property color main2_700: "#364860"
|
||||||
|
|
||||||
|
property color warning_600: "#DBB820"
|
||||||
|
|
||||||
|
property color grey_0: "#FFFFFF"
|
||||||
|
property color grey_500: "#4E4E4E"
|
||||||
|
property color grey_600: "#2E3030"
|
||||||
|
property color grey_900: "#070707"
|
||||||
|
|
||||||
|
property color danger_500: "#DD5F5F"
|
||||||
|
|
||||||
|
property color info_500_main: "#4AA8FF"
|
||||||
|
|
||||||
|
property color success_500main: "#4FAE80"
|
||||||
|
|
||||||
property string emojiFont: "Noto Color Emoji"
|
property string emojiFont: "Noto Color Emoji"
|
||||||
property color orangeColor: "#FE5E00"
|
|
||||||
property color buttonBackground: "#FE5E00"
|
|
||||||
property color buttonPressedBackground: "#c74b02"
|
property color buttonPressedBackground: "#c74b02"
|
||||||
property color buttonInversedBackground: "white"
|
|
||||||
property color buttonPressedInversedBackground: "#fff1e8"
|
property color buttonPressedInversedBackground: "#fff1e8"
|
||||||
property color buttonTextColor: "white"
|
|
||||||
property color radioButtonCheckedColor: "#4AA8FF"
|
|
||||||
property color radioButtonUncheckedColor: "#FE5E00"
|
|
||||||
property color radioButtonTitleColor: "#070707"
|
|
||||||
property int radioButtonTextSize: 8
|
property int radioButtonTextSize: 8
|
||||||
property int radioButtonTitleSize: 9
|
property int radioButtonTitleSize: 9
|
||||||
property color buttonInversedTextColor: "#FE5E00"
|
|
||||||
property color checkboxBorderColor: "#FE5E00"
|
|
||||||
property double checkboxBorderWidth: 2
|
property double checkboxBorderWidth: 2
|
||||||
property int buttonTextSize: 10
|
property int buttonTextSize: 10
|
||||||
property color carouselLightGrayColor: "#DFECF2"
|
property color carouselLightGrayColor: "#DFECF2"
|
||||||
|
|
@ -26,10 +39,8 @@ QtObject {
|
||||||
property color formItemDisableBackgroundColor: "#EDEDED"
|
property color formItemDisableBackgroundColor: "#EDEDED"
|
||||||
property color formItemBackgroundColor: "#F9F9F9"
|
property color formItemBackgroundColor: "#F9F9F9"
|
||||||
property color formItemBorderColor: "#EDEDED"
|
property color formItemBorderColor: "#EDEDED"
|
||||||
property color formItemFocusBorderColor: "#FE5E00"
|
|
||||||
|
|
||||||
property int tabButtonTextSize: 11
|
property int tabButtonTextSize: 11
|
||||||
property color verticalTabBarColor: "#FE5E00"
|
|
||||||
property color verticalTabBarTextColor: "white"
|
property color verticalTabBarTextColor: "white"
|
||||||
property int verticalTabButtonTextSize: 6
|
property int verticalTabButtonTextSize: 6
|
||||||
|
|
||||||
|
|
@ -43,7 +54,6 @@ QtObject {
|
||||||
|
|
||||||
property color tooltipBackgroundColor: "#DFECF2"
|
property color tooltipBackgroundColor: "#DFECF2"
|
||||||
|
|
||||||
property color digitInputFocusedColor: "#FE5E00"
|
|
||||||
property color digitInputColor: "#6C7A87"
|
property color digitInputColor: "#6C7A87"
|
||||||
|
|
||||||
property color darkBlueColor: "#22334D"
|
property color darkBlueColor: "#22334D"
|
||||||
|
|
@ -53,7 +63,8 @@ QtObject {
|
||||||
|
|
||||||
property color defaultTextColor: "#4E6074"
|
property color defaultTextColor: "#4E6074"
|
||||||
property color disableTextColor: "#9AABB5"
|
property color disableTextColor: "#9AABB5"
|
||||||
property int defaultTextSize: 7
|
property int descriptionTextSize: 7
|
||||||
|
property int indicatorMessageTextSize: 7
|
||||||
property string defaultFont: "Noto Sans"
|
property string defaultFont: "Noto Sans"
|
||||||
property int defaultFontPointSize: 10
|
property int defaultFontPointSize: 10
|
||||||
property int title1FontPointSize: 50
|
property int title1FontPointSize: 50
|
||||||
|
|
@ -65,29 +76,30 @@ QtObject {
|
||||||
property int mainPageTitleSize: 15
|
property int mainPageTitleSize: 15
|
||||||
|
|
||||||
property color searchBarFocusBorderColor: "#6C7A87"
|
property color searchBarFocusBorderColor: "#6C7A87"
|
||||||
|
property color contactListSearchBarColor: "#F9F9F9"
|
||||||
|
property color callRightPanelSearchBarBorderColor: "#EDEDED"
|
||||||
|
|
||||||
property color numericPadBackgroundColor: "#F9F9F9"
|
property color numericPadBackgroundColor: "#F9F9F9"
|
||||||
property color numericPadShadowColor: Qt.rgba(0.0, 0.0, 0.0, 0.1)
|
property color numericPadShadowColor: Qt.rgba(0.0, 0.0, 0.0, 0.1)
|
||||||
property color numericPadButtonColor: "#FFFFFF"
|
|
||||||
property int numericPadButtonTextSize: 15
|
property int numericPadButtonTextSize: 15
|
||||||
property int numericPadButtonSubtextSize: 6
|
property int numericPadButtonSubtextSize: 6
|
||||||
property color numericPadPressedButtonColor: "#EEF7F8"
|
property color numericPadPressedButtonColor: "#EEF7F8"
|
||||||
property color numericPadLaunchCallButtonColor: "#4FAE80"
|
|
||||||
|
|
||||||
property color groupCallButtonColor: "#EEF7F8"
|
property color groupCallButtonColor: "#EEF7F8"
|
||||||
|
property color launchCallButtonColor: "#4FAE80"
|
||||||
|
property color callCheckedButtonColor: "#9AABB5"
|
||||||
|
|
||||||
property color splitViewHandleColor: "#F9F9F9"
|
property color splitViewHandleColor: "#F9F9F9"
|
||||||
property color splitViewHoveredHandleColor: "#EDEDED"
|
property color splitViewHoveredHandleColor: "#EDEDED"
|
||||||
|
|
||||||
property color danger_500main: "#DD5F5F"
|
property color ongoingCallWindowColor: "#000000"
|
||||||
property color grey_0: "#FFFFFF"
|
property color ongoingCallBackgroundColor: "#2E3030"
|
||||||
property color success_500main: "#4FAE80"
|
property int ongoingCallElapsedTimeSize: 15
|
||||||
property color warning_600: "#DBB820"
|
property int ongoingCallNameSize: 10
|
||||||
property color main2_200: "#DFECF2"
|
property int ongoingCallAddressSize: 6
|
||||||
property color main2_300: "#C0D1D9"
|
property color callRightPanelBackgroundColor: "#F9F9F9"
|
||||||
property color main2_400: "#9AABB5"
|
|
||||||
property color main2_700: "#364860"
|
property color defaultAvatarBackgroundColor: "#DFECF2"
|
||||||
property color main2_500main: "#6C7A87"
|
|
||||||
|
|
||||||
property double dp: 1.0//0.66
|
property double dp: 1.0//0.66
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue