Use RC version to migrate Conference Factory URI

This commit is contained in:
Julien Wadel 2021-08-26 18:52:53 +02:00
parent e9ebd30680
commit e6934ec810
10 changed files with 450 additions and 710 deletions

View file

@ -2251,6 +2251,16 @@ Click here: <a href="%1">%1</a>
<source>mainSipAccountSettingsTitle</source>
<translation>Main SIP account settings</translation>
</message>
<message>
<source>conferenceURI</source>
<extracomment>&quot;Conference URI&quot; : Label of a text edit for filling Conference URI</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>invalidConferenceURI</source>
<extracomment>&quot;invalid conference URI&quot; : Error text about conference URI</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsUi</name>

View file

@ -45,9 +45,9 @@
#include "utils/Constants.hpp"
#if defined(Q_OS_MACOS)
#include "event-count-notifier/EventCountNotifierMacOs.hpp"
#include "event-count-notifier/EventCountNotifierMacOs.hpp"
#else
#include "event-count-notifier/EventCountNotifierSystemTrayIcon.hpp"
#include "event-count-notifier/EventCountNotifierSystemTrayIcon.hpp"
#endif // if defined(Q_OS_MACOS)
#include "CoreHandlers.hpp"
@ -102,7 +102,7 @@ void CoreManager::initCoreManager(){
QObject::connect(mEventCountNotifier, &EventCountNotifier::eventCountChanged,this, &CoreManager::eventCountChanged);
migrate();
mStarted = true;
qInfo() << QStringLiteral("CoreManager initialized");
emit coreManagerInitialized();
}
@ -112,57 +112,57 @@ AbstractEventCountNotifier * CoreManager::getEventCountNotifier(){
}
CoreManager *CoreManager::getInstance (){
return mInstance;
}
return mInstance;
}
HistoryModel* CoreManager::getHistoryModel(){
if(!mHistoryModel){
mHistoryModel = new HistoryModel(this);
emit historyModelCreated(mHistoryModel);
}
return mHistoryModel;
if(!mHistoryModel){
mHistoryModel = new HistoryModel(this);
emit historyModelCreated(mHistoryModel);
}
return mHistoryModel;
}
// -----------------------------------------------------------------------------
void CoreManager::init (QObject *parent, const QString &configPath) {
if (mInstance)
return;
mInstance = new CoreManager(parent, configPath);
if (mInstance)
return;
mInstance = new CoreManager(parent, configPath);
}
void CoreManager::uninit () {
if (mInstance) {
connect(mInstance, &QObject::destroyed, []()mutable{
mInstance = nullptr;
qInfo() << "Core is correctly destroyed";
});
QObject::connect(mInstance->getHandlers().get(), &CoreHandlers::coreStopped, mInstance, &QObject::deleteLater); // Delete data only when the core is Off
mInstance->lockVideoRender();// Stop do iterations. We have to protect GUI.
mInstance->mCore->stop();
mInstance->unlockVideoRender();
QTest::qWaitFor([&]() {return mInstance == nullptr;},10000);
if( mInstance){
qWarning() << "Core couldn't destroy in time. It may lead to have multiple session of Core";
mInstance = nullptr;
}
}
if (mInstance) {
connect(mInstance, &QObject::destroyed, []()mutable{
mInstance = nullptr;
qInfo() << "Core is correctly destroyed";
});
QObject::connect(mInstance->getHandlers().get(), &CoreHandlers::coreStopped, mInstance, &QObject::deleteLater); // Delete data only when the core is Off
mInstance->lockVideoRender();// Stop do iterations. We have to protect GUI.
mInstance->mCore->stop();
mInstance->unlockVideoRender();
QTest::qWaitFor([&]() {return mInstance == nullptr;},10000);
if( mInstance){
qWarning() << "Core couldn't destroy in time. It may lead to have multiple session of Core";
mInstance = nullptr;
}
}
}
// -----------------------------------------------------------------------------
VcardModel *CoreManager::createDetachedVcardModel () const {
VcardModel *vcardModel = new VcardModel(linphone::Factory::get()->createVcard(), false);
qInfo() << QStringLiteral("Create detached vcard:") << vcardModel;
return vcardModel;
VcardModel *vcardModel = new VcardModel(linphone::Factory::get()->createVcard(), false);
qInfo() << QStringLiteral("Create detached vcard:") << vcardModel;
return vcardModel;
}
void CoreManager::forceRefreshRegisters () {
Q_CHECK_PTR(mCore);
qInfo() << QStringLiteral("Refresh registers.");
mCore->refreshRegisters();
Q_CHECK_PTR(mCore);
qInfo() << QStringLiteral("Refresh registers.");
mCore->refreshRegisters();
}
void CoreManager::updateUnreadMessageCount(){
mEventCountNotifier->updateUnreadMessageCount();
@ -170,37 +170,37 @@ void CoreManager::updateUnreadMessageCount(){
// -----------------------------------------------------------------------------
void CoreManager::sendLogs () const {
Q_CHECK_PTR(mCore);
qInfo() << QStringLiteral("Send logs to: `%1` from `%2`.")
.arg(Utils::coreStringToAppString(mCore->getLogCollectionUploadServerUrl()))
.arg(Utils::coreStringToAppString(mCore->getLogCollectionPath()));
mCore->uploadLogCollection();
Q_CHECK_PTR(mCore);
qInfo() << QStringLiteral("Send logs to: `%1` from `%2`.")
.arg(Utils::coreStringToAppString(mCore->getLogCollectionUploadServerUrl()))
.arg(Utils::coreStringToAppString(mCore->getLogCollectionPath()));
mCore->uploadLogCollection();
}
void CoreManager::cleanLogs () const {
Q_CHECK_PTR(mCore);
mCore->resetLogCollection();
Q_CHECK_PTR(mCore);
mCore->resetLogCollection();
}
// -----------------------------------------------------------------------------
#define SET_DATABASE_PATH(DATABASE, PATH) \
do { \
qInfo() << QStringLiteral("Set `%1` path: `%2`") \
.arg( # DATABASE) \
.arg(Utils::coreStringToAppString(PATH)); \
mCore->set ## DATABASE ## DatabasePath(PATH); \
} while (0);
do { \
qInfo() << QStringLiteral("Set `%1` path: `%2`") \
.arg( # DATABASE) \
.arg(Utils::coreStringToAppString(PATH)); \
mCore->set ## DATABASE ## DatabasePath(PATH); \
} while (0);
void CoreManager::setDatabasesPaths () {
SET_DATABASE_PATH(Friends, Paths::getFriendsListFilePath());
SET_DATABASE_PATH(CallLogs, Paths::getCallHistoryFilePath());
if(QFile::exists(Utils::coreStringToAppString(Paths::getMessageHistoryFilePath()))){
linphone_core_set_chat_database_path(mCore->cPtr(), Paths::getMessageHistoryFilePath().c_str());// Setting the message database let SDK to migrate data
QFile::remove(Utils::coreStringToAppString(Paths::getMessageHistoryFilePath()));
}
SET_DATABASE_PATH(Friends, Paths::getFriendsListFilePath());
SET_DATABASE_PATH(CallLogs, Paths::getCallHistoryFilePath());
if(QFile::exists(Utils::coreStringToAppString(Paths::getMessageHistoryFilePath()))){
linphone_core_set_chat_database_path(mCore->cPtr(), Paths::getMessageHistoryFilePath().c_str());// Setting the message database let SDK to migrate data
QFile::remove(Utils::coreStringToAppString(Paths::getMessageHistoryFilePath()));
}
}
#undef SET_DATABASE_PATH
@ -208,64 +208,64 @@ void CoreManager::setDatabasesPaths () {
// -----------------------------------------------------------------------------
void CoreManager::setOtherPaths () {
if (mCore->getZrtpSecretsFile().empty() || !Paths::filePathExists(mCore->getZrtpSecretsFile()))
mCore->setZrtpSecretsFile(Paths::getZrtpSecretsFilePath());
if (mCore->getUserCertificatesPath().empty() || !Paths::filePathExists(mCore->getUserCertificatesPath()))
mCore->setUserCertificatesPath(Paths::getUserCertificatesDirPath());
if (mCore->getRootCa().empty() || !Paths::filePathExists(mCore->getRootCa()))
mCore->setRootCa(Paths::getRootCaFilePath());
if (mCore->getZrtpSecretsFile().empty() || !Paths::filePathExists(mCore->getZrtpSecretsFile()))
mCore->setZrtpSecretsFile(Paths::getZrtpSecretsFilePath());
if (mCore->getUserCertificatesPath().empty() || !Paths::filePathExists(mCore->getUserCertificatesPath()))
mCore->setUserCertificatesPath(Paths::getUserCertificatesDirPath());
if (mCore->getRootCa().empty() || !Paths::filePathExists(mCore->getRootCa()))
mCore->setRootCa(Paths::getRootCaFilePath());
}
void CoreManager::setResourcesPaths () {
shared_ptr<linphone::Factory> factory = linphone::Factory::get();
factory->setMspluginsDir(Paths::getPackageMsPluginsDirPath());
factory->setTopResourcesDir(Paths::getPackageDataDirPath());
shared_ptr<linphone::Factory> factory = linphone::Factory::get();
factory->setMspluginsDir(Paths::getPackageMsPluginsDirPath());
factory->setTopResourcesDir(Paths::getPackageDataDirPath());
}
// -----------------------------------------------------------------------------
void CoreManager::createLinphoneCore (const QString &configPath) {
qInfo() << QStringLiteral("Launch async core creation.");
// Migration of configuration and database files from GTK version of Linphone.
Paths::migrate();
setResourcesPaths();
mCore = linphone::Factory::get()->createCore(
Paths::getConfigFilePath(configPath),
Paths::getFactoryConfigFilePath(),
nullptr
);
// You only need to give your LIME server URL
mCore->setLimeX3DhServerUrl("https://lime.linphone.org/lime-server/lime-server.php");
qInfo() << QStringLiteral("Launch async core creation.");
// Migration of configuration and database files from GTK version of Linphone.
Paths::migrate();
setResourcesPaths();
mCore = linphone::Factory::get()->createCore(
Paths::getConfigFilePath(configPath),
Paths::getFactoryConfigFilePath(),
nullptr
);
// You only need to give your LIME server URL
mCore->setLimeX3DhServerUrl("https://lime.linphone.org/lime-server/lime-server.php");
// and enable LIME on your core to use encryption.
mCore->enableLimeX3Dh(true);
// Now see the CoreService.CreateGroupChatRoom to see how to create a secure chat room
mCore->addListener(mHandlers);
mCore->setVideoDisplayFilter("MSQOGL");
mCore->usePreviewWindow(true);
mCore->enableVideoPreview(false);
mCore->setUserAgent(
Utils::appStringToCoreString(
QStringLiteral(APPLICATION_NAME" Desktop/%1 (%2, Qt %3) LinphoneCore")
.arg(QCoreApplication::applicationVersion())
.arg(QSysInfo::prettyProductName())
.arg(qVersion())
),
mCore->getVersion()
);
// Force capture/display.
// Useful if the app was built without video support.
// (The capture/display attributes are reset by the core in this case.)
if (mCore->videoSupported()) {
shared_ptr<linphone::Config> config = mCore->getConfig();
config->setInt("video", "capture", 1);
config->setInt("video", "display", 1);
}
mCore->start();
setDatabasesPaths();
setOtherPaths();
mCore->enableFriendListSubscription(true);
mCore->enableLimeX3Dh(true);
// Now see the CoreService.CreateGroupChatRoom to see how to create a secure chat room
mCore->addListener(mHandlers);
mCore->setVideoDisplayFilter("MSQOGL");
mCore->usePreviewWindow(true);
mCore->enableVideoPreview(false);
mCore->setUserAgent(
Utils::appStringToCoreString(
QStringLiteral(APPLICATION_NAME" Desktop/%1 (%2, Qt %3) LinphoneCore")
.arg(QCoreApplication::applicationVersion())
.arg(QSysInfo::prettyProductName())
.arg(qVersion())
),
mCore->getVersion()
);
// Force capture/display.
// Useful if the app was built without video support.
// (The capture/display attributes are reset by the core in this case.)
if (mCore->videoSupported()) {
shared_ptr<linphone::Config> config = mCore->getConfig();
config->setInt("video", "capture", 1);
config->setInt("video", "display", 1);
}
mCore->start();
setDatabasesPaths();
setOtherPaths();
mCore->enableFriendListSubscription(true);
}
void CoreManager::handleChatRoomCreated(const std::shared_ptr<ChatRoomModel> &chatRoomModel){
@ -273,51 +273,56 @@ void CoreManager::handleChatRoomCreated(const std::shared_ptr<ChatRoomModel> &ch
}
void CoreManager::migrate () {
shared_ptr<linphone::Config> config = mCore->getConfig();
int rcVersion = config->getInt(SettingsModel::UiSection, Constants::RcVersionName, 0);
if (rcVersion == Constants::RcVersionCurrent)
return;
if (rcVersion > Constants::RcVersionCurrent) {
qWarning() << QStringLiteral("RC file version (%1) is more recent than app rc file version (%2)!!!")
.arg(rcVersion).arg(Constants::RcVersionCurrent);
return;
}
qInfo() << QStringLiteral("Migrate from old rc file (%1 to %2).")
.arg(rcVersion).arg(Constants::RcVersionCurrent);
// Add message_expires param on old proxy configs.
/*
for (const auto &proxyConfig : mCore->getProxyConfigList()) {
if (proxyConfig->getDomain() == Constants::LinphoneDomain) {
proxyConfig->setContactParameters(Constants::DefaultContactParameters);
proxyConfig->setExpires(Constants::DefaultExpires);
proxyConfig->done();
}
}*/
for(const auto &account : mCore->getAccountList()){
auto params = account->getParams();
if( params->getDomain() == Constants::LinphoneDomain) {
auto newParams = params->clone();
newParams->setContactParameters(Constants::DefaultContactParameters);
newParams->setExpires(Constants::DefaultExpires);
account->setParams(newParams);
shared_ptr<linphone::Config> config = mCore->getConfig();
int rcVersion = config->getInt(SettingsModel::UiSection, Constants::RcVersionName, 0);
if (rcVersion == Constants::RcVersionCurrent)
return;
if (rcVersion > Constants::RcVersionCurrent) {
qWarning() << QStringLiteral("RC file version (%1) is more recent than app rc file version (%2)!!!")
.arg(rcVersion).arg(Constants::RcVersionCurrent);
return;
}
}
config->setInt(SettingsModel::UiSection, Constants::RcVersionName, Constants::RcVersionCurrent);
qInfo() << QStringLiteral("Migrate from old rc file (%1 to %2).")
.arg(rcVersion).arg(Constants::RcVersionCurrent);
// Add message_expires param on old proxy configs.
/*
for (const auto &proxyConfig : mCore->getProxyConfigList()) {
if (proxyConfig->getDomain() == Constants::LinphoneDomain) {
proxyConfig->setContactParameters(Constants::DefaultContactParameters);
proxyConfig->setExpires(Constants::DefaultExpires);
proxyConfig->done();
}
}*/
for(const auto &account : mCore->getAccountList()){
auto params = account->getParams();
if( params->getDomain() == Constants::LinphoneDomain) {
auto newParams = params->clone();
if( rcVersion < 1) {
newParams->setContactParameters(Constants::DefaultContactParameters);
newParams->setExpires(Constants::DefaultExpires);
}
if( rcVersion < 2) {
newParams->setConferenceFactoryUri(Constants::DefaultConferenceURI);
}
account->setParams(newParams);
}
}
config->setInt(SettingsModel::UiSection, Constants::RcVersionName, Constants::RcVersionCurrent);
}
// -----------------------------------------------------------------------------
QString CoreManager::getVersion () const {
return Utils::coreStringToAppString(mCore->getVersion());
return Utils::coreStringToAppString(mCore->getVersion());
}
// -----------------------------------------------------------------------------
int CoreManager::getEventCount () const {
return mEventCountNotifier ? mEventCountNotifier->getEventCount() : 0;
return mEventCountNotifier ? mEventCountNotifier->getEventCount() : 0;
}
int CoreManager::getMissedCallCount(const QString &peerAddress, const QString &localAddress)const{
return mEventCountNotifier ? mEventCountNotifier->getMissedCallCount(peerAddress, localAddress) : 0;
@ -329,45 +334,45 @@ int CoreManager::getMissedCallCountFromLocal( const QString &localAddress)const{
// -----------------------------------------------------------------------------
void CoreManager::startIterate(){
mCbsTimer = new QTimer(this);
mCbsTimer->setInterval(Constants::CbsCallInterval);
QObject::connect(mCbsTimer, &QTimer::timeout, this, &CoreManager::iterate);
qInfo() << QStringLiteral("Start iterate");
mCbsTimer->start();
mCbsTimer = new QTimer(this);
mCbsTimer->setInterval(Constants::CbsCallInterval);
QObject::connect(mCbsTimer, &QTimer::timeout, this, &CoreManager::iterate);
qInfo() << QStringLiteral("Start iterate");
mCbsTimer->start();
}
void CoreManager::stopIterate(){
qInfo() << QStringLiteral("Stop iterate");
mCbsTimer->stop();
mCbsTimer->deleteLater();// allow the timer to continue its stuff
mCbsTimer = nullptr;
qInfo() << QStringLiteral("Stop iterate");
mCbsTimer->stop();
mCbsTimer->deleteLater();// allow the timer to continue its stuff
mCbsTimer = nullptr;
}
void CoreManager::iterate () {
lockVideoRender();
if(mCore)
mCore->iterate();
unlockVideoRender();
lockVideoRender();
if(mCore)
mCore->iterate();
unlockVideoRender();
}
// -----------------------------------------------------------------------------
void CoreManager::handleLogsUploadStateChanged (linphone::Core::LogCollectionUploadState state, const string &info) {
switch (state) {
case linphone::Core::LogCollectionUploadState::InProgress:
break;
case linphone::Core::LogCollectionUploadState::Delivered:
case linphone::Core::LogCollectionUploadState::NotDelivered:
emit logsUploaded(Utils::coreStringToAppString(info));
break;
}
switch (state) {
case linphone::Core::LogCollectionUploadState::InProgress:
break;
case linphone::Core::LogCollectionUploadState::Delivered:
case linphone::Core::LogCollectionUploadState::NotDelivered:
emit logsUploaded(Utils::coreStringToAppString(info));
break;
}
}
// -----------------------------------------------------------------------------
QString CoreManager::getDownloadUrl () {
return Constants::DownloadUrl;
return Constants::DownloadUrl;
}
void CoreManager::setLastRemoteProvisioningState(const linphone::ConfiguringState& state){

View file

@ -139,8 +139,6 @@ QVariantMap AccountSettingsModel::getProxyConfigDescription (const shared_ptr<li
else
map["route"] = "";
map["conferenceUri"] = Utils::coreStringToAppString(proxyConfig->getConferenceFactoryUri());
if(map["conferenceUri"] == "")
map["conferenceUri"] = Constants::DefaultConferenceURI;
map["contactParams"] = Utils::coreStringToAppString(proxyConfig->getContactParameters());
map["avpfInterval"] = proxyConfig->getAvpfRrInterval();
map["registerEnabled"] = proxyConfig->registerEnabled();
@ -175,9 +173,7 @@ QVariantMap AccountSettingsModel::getProxyConfigDescription (const shared_ptr<li
QString AccountSettingsModel::getConferenceURI() const{
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
shared_ptr<linphone::ProxyConfig> proxyConfig = core->getDefaultProxyConfig();
if( proxyConfig && proxyConfig->getConferenceFactoryUri() == "")
proxyConfig->setConferenceFactoryUri(Utils::appStringToCoreString(Constants::DefaultConferenceURI));
return proxyConfig ? Utils::coreStringToAppString(proxyConfig->getConferenceFactoryUri()) : Constants::DefaultConferenceURI;
return proxyConfig ? Utils::coreStringToAppString(proxyConfig->getConferenceFactoryUri()) : "";
}
void AccountSettingsModel::setDefaultProxyConfig (const shared_ptr<linphone::ProxyConfig> &proxyConfig) {
@ -259,7 +255,9 @@ bool AccountSettingsModel::addOrUpdateProxyConfig (
proxyConfig->setPublishExpires(data["registrationDuration"].toInt());
proxyConfig->setRoute(Utils::appStringToCoreString(data["route"].toString()));
proxyConfig->setConferenceFactoryUri(Utils::appStringToCoreString(data["conferenceUri"].toString()));
QString conferenceURI = data["conferenceUri"].toString();
if(!conferenceURI.isEmpty())
proxyConfig->setConferenceFactoryUri(Utils::appStringToCoreString(conferenceURI));
proxyConfig->setContactParameters(Utils::appStringToCoreString(data["contactParams"].toString()));
proxyConfig->setAvpfRrInterval(uint8_t(data["avpfInterval"].toInt()));
proxyConfig->enableRegister(data["registerEnabled"].toBool());

View file

@ -1,102 +0,0 @@
/*
* Copyright (c) 2010-2020 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 "components/core/CoreManager.hpp"
#include "components/settings/AccountSettingsModel.hpp"
#include "components/sip-addresses/SipAddressesModel.hpp"
#include "utils/Utils.hpp"
#include "TimelineModel.hpp"
#include <QDebug>
// =============================================================================
TimelineModel::TimelineModel (QObject *parent) : QSortFilterProxyModel(parent) {
CoreManager *coreManager = CoreManager::getInstance();
AccountSettingsModel *accountSettingsModel = coreManager->getAccountSettingsModel();
QObject::connect(accountSettingsModel, &AccountSettingsModel::accountSettingsUpdated, this, [this]() {
handleLocalAddressChanged(CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddressAsStringUriOnly());
});
QObject::connect(coreManager->getSipAddressesModel(), &SipAddressesModel::sipAddressReset, this, [this]() {
invalidate();// Invalidate and reload GUI if the model has been reset
});
mLocalAddress = accountSettingsModel->getUsedSipAddressAsStringUriOnly();
setSourceModel(coreManager->getSipAddressesModel());
sort(0);
}
QHash<int, QByteArray> TimelineModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$timelineEntry";
return roles;
}
// -----------------------------------------------------------------------------
static inline const QHash<QString, SipAddressesModel::ConferenceEntry> *getLocalToConferenceEntry (const QVariantMap &map) {
return map.value("__localToConferenceEntry").value<decltype(getLocalToConferenceEntry({}))>();
}
QVariant TimelineModel::data (const QModelIndex &index, int role) const {
QVariantMap map(QSortFilterProxyModel::data(index, role).toMap());
auto localToConferenceEntry = getLocalToConferenceEntry(map);
auto it = localToConferenceEntry->find(getCleanedLocalAddress());
if (it != localToConferenceEntry->end()) {
map["timestamp"] = it->timestamp;
map["isComposing"] = it->isComposing;
map["unreadMessageCount"] = it->unreadMessageCount;
map["missedCallCount"] = it->missedCallCount;
}
return map;
}
bool TimelineModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const {
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
return getLocalToConferenceEntry(index.data().toMap())->contains(getCleanedLocalAddress());
}
bool TimelineModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
QString localAddress = getCleanedLocalAddress();
const QDateTime &a(getLocalToConferenceEntry(sourceModel()->data(left).toMap())->find(localAddress)->timestamp);
const QDateTime &b(getLocalToConferenceEntry(sourceModel()->data(right).toMap())->find(localAddress)->timestamp);
return a > b;
}
// -----------------------------------------------------------------------------
QString TimelineModel::getLocalAddress () const
{
return mLocalAddress;
}
QString TimelineModel::getCleanedLocalAddress () const
{
return Utils::cleanSipAddress(mLocalAddress);
}
void TimelineModel::handleLocalAddressChanged (const QString &localAddress) {
if (mLocalAddress != localAddress) {
mLocalAddress = localAddress;
invalidate();
}
}

View file

@ -1,54 +0,0 @@
/*
* Copyright (c) 2010-2020 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 TIMELINE_MODEL_H_
#define TIMELINE_MODEL_H_
#include <QSortFilterProxyModel>
// =============================================================================
class TimelineModel : public QSortFilterProxyModel {
Q_OBJECT;
Q_PROPERTY(QString localAddress READ getLocalAddress NOTIFY localAddressChanged);
public:
TimelineModel (QObject *parent = Q_NULLPTR);
QHash<int, QByteArray> roleNames () const override;
signals:
void localAddressChanged (const QString &localAddress);
protected:
QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
bool lessThan (const QModelIndex &left, const QModelIndex &right) const override;
QString getLocalAddress () const;
QString getCleanedLocalAddress () const;
void handleLocalAddressChanged (const QString &localAddress);
private:
QString mLocalAddress;
};
#endif // TIMELINE_MODEL_H_

View file

@ -113,7 +113,7 @@ public:
static constexpr char VcardScheme[] = "linphone-desktop:/";
static constexpr int CbsCallInterval = 20;
static constexpr char RcVersionName[] = "rc_version";
static constexpr int RcVersionCurrent = 1;
static constexpr int RcVersionCurrent = 2;// 2 = Conference URI
//--------------------------------------------------------------------------------
// CISCO

View file

@ -1,118 +0,0 @@
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import Common 1.0
import Linphone 1.0
import Linphone.Styles 1.0
// =============================================================================
Item {
id: accountStatus
// ---------------------------------------------------------------------------
signal clicked
property alias cursorShape:mouseArea.cursorShape
property alias betterIcon : presenceLevel.betterIcon
// ---------------------------------------------------------------------------
Row {
anchors.fill: parent
Column {
//Layout.fillWidth: true
//Layout.fillHeight: true
anchors.fill:parent
spacing: AccountStatusStyle.verticalSpacing
Row {
height: parent.height / 2
spacing: AccountStatusStyle.horizontalSpacing
//width: parent.width
Item {
//Layout.alignment: Qt.AlignBottom
//Layout.bottomMargin: AccountStatusStyle.presenceLevel.bottomMargin
//Layout.preferredHeight: AccountStatusStyle.presenceLevel.size
//Layout.preferredWidth: AccountStatusStyle.presenceLevel.size
height: AccountStatusStyle.presenceLevel.size
width: AccountStatusStyle.presenceLevel.size
anchors.bottom:parent.bottom
anchors.bottomMargin: AccountStatusStyle.presenceLevel.bottomMargin
PresenceLevel {
id:presenceLevel
anchors.fill: parent
level: OwnPresenceModel.presenceStatus===Presence.Offline?Presence.White:( SettingsModel.rlsUriEnabled ? OwnPresenceModel.presenceLevel : Presence.Green)
visible: AccountSettingsModel.registrationState === AccountSettingsModel.RegistrationStateRegistered
}
BusyIndicator {
anchors.fill: parent
running: AccountSettingsModel.registrationState === AccountSettingsModel.RegistrationStateInProgress
}
Icon {
iconSize: parent.width
icon: 'generic_error'
visible: AccountSettingsModel.registrationState === AccountSettingsModel.RegistrationStateNotRegistered || AccountSettingsModel.registrationState === AccountSettingsModel.RegistrationStateNoProxy
TooltipArea{
text : 'Not Registered'
}
}
}
Text {
id:username
anchors.bottom:parent.bottom
//Layout.fillHeight: true
//Layout.fillWidth: true
color: AccountStatusStyle.username.color
elide: Text.ElideRight
font.bold: true
font.pointSize: AccountStatusStyle.username.pointSize
text: AccountSettingsModel.username
verticalAlignment: Text.AlignBottom
}
Item {
// Layout.bottomMargin: -AccountStatusStyle.presenceLevel.bottomMargin
//Layout.preferredHeight: AccountStatusStyle.presenceLevel.size
//Layout.preferredWidth: AccountStatusStyle.presenceLevel.size
height: AccountStatusStyle.messageCounter.size
width: AccountStatusStyle.messageCounter.size
anchors.bottom:parent.bottom
anchors.bottomMargin: AccountStatusStyle.messageCounter.bottomMargin
MessageCounter {
id: messageCounter
//iconSize: parent.height
anchors.fill: parent
count: CoreManager.eventCount
}
}
}
Text {
color: AccountStatusStyle.sipAddress.color
elide: Text.ElideRight
font.pointSize: AccountStatusStyle.sipAddress.pointSize
height: parent.height / 2
text: AccountSettingsModel.sipAddress
verticalAlignment: Text.AlignTop
width: parent.width
}
}
}
MouseArea {
id:mouseArea
anchors.fill: parent
onClicked: accountStatus.clicked()
}
}

View file

@ -107,7 +107,7 @@ function handleRouteChanged (route) {
dialog._routeOk = route.length === 0 || Linphone.SipAddressesModel.addressIsValid(route)
}
function handleConferenceUriChanged (uri) {
dialog._conferenceUriOk = route.length === 0 || Linphone.SipAddressesModel.addressIsValid(uri)
dialog._conferenceUriOk = Linphone.SipAddressesModel.addressIsValid(uri)
}
function handleServerAddressChanged (address) {

View file

@ -9,269 +9,270 @@ import 'SettingsSipAccountsEdit.js' as Logic
// =============================================================================
DialogPlus {
id: dialog
property var account // Optional.
property bool _sipAddressOk: false
property bool _serverAddressOk: false
property bool _routeOk: false
property bool _conferenceUriOk: false
buttons: [
TextButtonA {
text: qsTr('cancel')
onClicked: exit(0)
},
TextButtonB {
enabled: Logic.formIsValid()
text: qsTr('confirm')
onClicked: Logic.validProxyConfig()
}
]
buttonsAlignment: Qt.AlignCenter
height: SettingsSipAccountsEditStyle.height
width: SettingsSipAccountsEditStyle.width
// ---------------------------------------------------------------------------
Component.onCompleted: Logic.initForm(account)
// ---------------------------------------------------------------------------
TabContainer {
anchors.fill: parent
Column {
width: parent.width
Form {
title: qsTr('mainSipAccountSettingsTitle')
width: parent.width
FormLine {
FormGroup {
label: qsTr('sipAddressLabel') + '*'
TextField {
id: sipAddress
placeholderText: 'sip:name@sip.example.net'
error: dialog._sipAddressOk ? '' : qsTr('invalidSipAddress')
onTextChanged: Logic.handleSipAddressChanged(text)
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {
label: qsTr('serverAddressLabel') + '*'
TextField {
id: serverAddress
placeholderText: 'sip:sip.example.net'
error: dialog._serverAddressOk ? '' : qsTr('invalidServerAddress')
onActiveFocusChanged: if(!activeFocus && dialog._serverAddressOk) Logic.handleTransportChanged(transport.model[transport.currentIndex])
onTextChanged: Logic.handleServerAddressChanged(text)
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {
label: qsTr('registrationDurationLabel')
NumericField {
id: registrationDuration
Keys.onReturnPressed: route.forceActiveFocus()
}
}
}
FormLine {
FormGroup {
label: qsTr('transportLabel')
ComboBox {
id: transport
enabled: dialog._serverAddressOk
model: [ 'UDP', 'TCP', 'TLS' ]
onActivated: Logic.handleTransportChanged(model[index])
}
}
}
FormLine {
FormGroup {
label: qsTr('routeLabel')
TextField {
id: route
error: dialog._routeOk ? '' : qsTr('invalidRoute')
onTextChanged: Logic.handleRouteChanged(text)
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
id: dialog
property var account // Optional.
property bool _sipAddressOk: false
property bool _serverAddressOk: false
property bool _routeOk: false
property bool _conferenceUriOk: false
buttons: [
TextButtonA {
text: qsTr('cancel')
onClicked: exit(0)
},
TextButtonB {
enabled: Logic.formIsValid()
text: qsTr('confirm')
onClicked: Logic.validProxyConfig()
}
]
buttonsAlignment: Qt.AlignCenter
height: SettingsSipAccountsEditStyle.height
width: SettingsSipAccountsEditStyle.width
// ---------------------------------------------------------------------------
Component.onCompleted: Logic.initForm(account)
// ---------------------------------------------------------------------------
TabContainer {
anchors.fill: parent
FormLine {
FormGroup {
label: 'Conference URI'
TextField {
id: conferenceUri
error: dialog._conferenceUriOk ? '' : 'invalid conference uri'
onTextChanged: Logic.handleConferenceUriChanged(text)
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {
label: qsTr('contactParamsLabel')
TextField {
id: contactParams
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {
label: qsTr('avpfIntervalLabel')
NumericField {
id: avpfInterval
maxValue: 5
minValue: 1
Keys.onReturnPressed: focus=false
}
}
}
FormLine {
FormGroup {
label: qsTr('registerEnabledLabel')
Switch {
id: registerEnabled
onClicked: checked = !checked
}
}
}
FormLine {
FormGroup {
label: qsTr('publishPresenceLabel')
Switch {
id: publishPresence
onClicked: checked = !checked
}
}
}
FormLine {
FormGroup {
label: qsTr('avpfEnabledLabel')
Switch {
id: avpfEnabled
onClicked: checked = !checked
}
}
}
}
// -----------------------------------------------------------------------
// NAT and Firewall.
// -----------------------------------------------------------------------
Form {
title: qsTr('natAndFirewallTitle')
width: parent.width
FormLine {
FormGroup {
label: qsTr('enableIceLabel')
Switch {
id: iceEnabled
onClicked: checked = !checked
}
}
FormGroup {
label: qsTr('stunServerLabel')
TextField {
id: stunServer
placeholderText: 'stun.example.net'
readOnly: !iceEnabled.checked
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {
label: qsTr('enableTurnLabel')
Switch {
id: turnEnabled
enabled: iceEnabled.checked
onClicked: checked = !checked
}
}
FormGroup {
label: qsTr('turnUserLabel')
TextField {
id: turnUser
readOnly: !turnEnabled.checked || !turnEnabled.enabled
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {}
FormGroup {
label: qsTr('turnPasswordLabel')
TextField {
id: turnPassword
readOnly: !turnEnabled.checked || !turnEnabled.enabled || !turnUser.text.length
}
}
}
}
}
}
Column {
width: parent.width
Form {
title: qsTr('mainSipAccountSettingsTitle')
width: parent.width
FormLine {
FormGroup {
label: qsTr('sipAddressLabel') + '*'
TextField {
id: sipAddress
placeholderText: 'sip:name@sip.example.net'
error: dialog._sipAddressOk ? '' : qsTr('invalidSipAddress')
onTextChanged: Logic.handleSipAddressChanged(text)
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {
label: qsTr('serverAddressLabel') + '*'
TextField {
id: serverAddress
placeholderText: 'sip:sip.example.net'
error: dialog._serverAddressOk ? '' : qsTr('invalidServerAddress')
onActiveFocusChanged: if(!activeFocus && dialog._serverAddressOk) Logic.handleTransportChanged(transport.model[transport.currentIndex])
onTextChanged: Logic.handleServerAddressChanged(text)
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {
label: qsTr('registrationDurationLabel')
NumericField {
id: registrationDuration
Keys.onReturnPressed: route.forceActiveFocus()
}
}
}
FormLine {
FormGroup {
label: qsTr('transportLabel')
ComboBox {
id: transport
enabled: dialog._serverAddressOk
model: [ 'UDP', 'TCP', 'TLS' ]
onActivated: Logic.handleTransportChanged(model[index])
}
}
}
FormLine {
FormGroup {
label: qsTr('routeLabel')
TextField {
id: route
error: dialog._routeOk ? '' : qsTr('invalidRoute')
onTextChanged: Logic.handleRouteChanged(text)
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {
//: "Conference URI" : Label of a text edit for filling Conference URI
label: qsTr('conferenceURI')
TextField {
id: conferenceUri
//: "invalid conference URI" : Error text about conference URI
error: dialog._conferenceUriOk ? '' : qsTr("invalidConferenceURI")
onTextChanged: Logic.handleConferenceUriChanged(text)
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {
label: qsTr('contactParamsLabel')
TextField {
id: contactParams
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {
label: qsTr('avpfIntervalLabel')
NumericField {
id: avpfInterval
maxValue: 5
minValue: 1
Keys.onReturnPressed: focus=false
}
}
}
FormLine {
FormGroup {
label: qsTr('registerEnabledLabel')
Switch {
id: registerEnabled
onClicked: checked = !checked
}
}
}
FormLine {
FormGroup {
label: qsTr('publishPresenceLabel')
Switch {
id: publishPresence
onClicked: checked = !checked
}
}
}
FormLine {
FormGroup {
label: qsTr('avpfEnabledLabel')
Switch {
id: avpfEnabled
onClicked: checked = !checked
}
}
}
}
// -----------------------------------------------------------------------
// NAT and Firewall.
// -----------------------------------------------------------------------
Form {
title: qsTr('natAndFirewallTitle')
width: parent.width
FormLine {
FormGroup {
label: qsTr('enableIceLabel')
Switch {
id: iceEnabled
onClicked: checked = !checked
}
}
FormGroup {
label: qsTr('stunServerLabel')
TextField {
id: stunServer
placeholderText: 'stun.example.net'
readOnly: !iceEnabled.checked
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {
label: qsTr('enableTurnLabel')
Switch {
id: turnEnabled
enabled: iceEnabled.checked
onClicked: checked = !checked
}
}
FormGroup {
label: qsTr('turnUserLabel')
TextField {
id: turnUser
readOnly: !turnEnabled.checked || !turnEnabled.enabled
Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()
}
}
}
FormLine {
FormGroup {}
FormGroup {
label: qsTr('turnPasswordLabel')
TextField {
id: turnPassword
readOnly: !turnEnabled.checked || !turnEnabled.enabled || !turnUser.text.length
}
}
}
}
}
}
}

@ -1 +1 @@
Subproject commit 90d0649aa68f0730817eaef9930522700ceb0253
Subproject commit ecd5e0be3e83efba08759ed7f865d770eda6a5ff