secure first step

This commit is contained in:
Julien Wadel 2021-04-29 15:14:50 +02:00
parent 443b359256
commit c74654204a
26 changed files with 899 additions and 129 deletions

View file

@ -165,6 +165,8 @@ set(SOURCES
src/components/sound-player/SoundPlayer.cpp
src/components/telephone-numbers/TelephoneNumbersModel.cpp
src/components/timeline/TimelineModel.cpp
src/components/timeline/TimelineListModel.cpp
src/components/timeline/TimelineProxyModel.cpp
src/components/url-handlers/UrlHandlers.cpp
src/utils/LinphoneUtils.cpp
src/utils/MediastreamerUtils.cpp
@ -241,6 +243,8 @@ set(HEADERS
src/components/sound-player/SoundPlayer.hpp
src/components/telephone-numbers/TelephoneNumbersModel.hpp
src/components/timeline/TimelineModel.hpp
src/components/timeline/TimelineListModel.hpp
src/components/timeline/TimelineProxyModel.hpp
src/components/url-handlers/UrlHandlers.hpp
src/utils/LinphoneUtils.hpp
src/utils/MediastreamerUtils.hpp

View file

@ -48,6 +48,10 @@
#include "utils/Utils.hpp"
#include "components/other/desktop-tools/DesktopTools.hpp"
#include "components/timeline/TimelineModel.hpp"
#include "components/timeline/TimelineListModel.hpp"
#include "components/timeline/TimelineProxyModel.hpp"
// =============================================================================
using namespace std;
@ -581,6 +585,7 @@ void App::registerTypes () {
qRegisterMetaType<ChatModel::EntryType>();
qRegisterMetaType<shared_ptr<linphone::SearchResult>>();
qRegisterMetaType<std::list<std::shared_ptr<linphone::SearchResult> > >();
qRegisterMetaType<std::shared_ptr<ChatModel>>();
registerType<AssistantModel>("AssistantModel");
registerType<AuthenticationNotifier>("AuthenticationNotifier");
@ -599,13 +604,14 @@ void App::registerTypes () {
registerType<SipAddressesProxyModel>("SipAddressesProxyModel");
registerType<SearchSipAddressesModel>("SearchSipAddressesModel");
registerType<TimelineProxyModel>("TimelineProxyModel");
registerType<SoundPlayer>("SoundPlayer");
registerType<TelephoneNumbersModel>("TelephoneNumbersModel");
registerSingletonType<AudioCodecsModel>("AudioCodecsModel");
registerSingletonType<OwnPresenceModel>("OwnPresenceModel");
registerSingletonType<Presence>("Presence");
registerSingletonType<TimelineModel>("TimelineModel");
//registerSingletonType<TimelineModel>("TimelineModel");
registerSingletonType<UrlHandlers>("UrlHandlers");
registerSingletonType<VideoCodecsModel>("VideoCodecsModel");
@ -618,6 +624,7 @@ void App::registerTypes () {
registerUncreatableType<LdapModel>("LdapModel");
registerUncreatableType<SipAddressObserver>("SipAddressObserver");
registerUncreatableType<VcardModel>("VcardModel");
registerUncreatableType<TimelineModel>("TimelineModel");
}
void App::registerSharedTypes () {
@ -632,6 +639,7 @@ void App::registerSharedTypes () {
registerSharedSingletonType<ContactsListModel, &CoreManager::getContactsListModel>("ContactsListModel");
registerSharedSingletonType<ContactsImporterListModel, &CoreManager::getContactsImporterListModel>("ContactsImporterListModel");
registerSharedSingletonType<LdapListModel, &CoreManager::getLdapListModel>("LdapListModel");
registerSharedSingletonType<TimelineListModel, &CoreManager::getTimelineListModel>("TimelineListModel");
}
void App::registerToolTypes () {

View file

@ -59,6 +59,8 @@
#include "sound-player/SoundPlayer.hpp"
#include "telephone-numbers/TelephoneNumbersModel.hpp"
#include "timeline/TimelineModel.hpp"
#include "timeline/TimelineProxyModel.hpp"
#include "timeline/TimelineListModel.hpp"
#include "url-handlers/UrlHandlers.hpp"
#include "other/colors/Colors.hpp"

View file

@ -151,6 +151,38 @@ void CallsListModel::launchVideoCall (const QString &sipAddress) const {
core->inviteAddressWithParams(address, params);
}
bool CallsListModel::launchSecureChat (const QString &sipAddress) const {
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
shared_ptr<linphone::Address> address = core->interpretUrl(Utils::appStringToCoreString(sipAddress));
if (!address)
return false;
std::shared_ptr<linphone::ChatRoomParams> params = core->createDefaultChatRoomParams();
std::list <shared_ptr<linphone::Address> > participants;
std::shared_ptr<const linphone::Address> localAddress;
participants.push_back(address);
auto proxy = core->getDefaultProxyConfig();
params->enableEncryption(true);
params->setSubject("This is Desktop test");
params->setBackend(linphone::ChatRoomBackend::FlexisipChat);
params->setEncryptionBackend(linphone::ChatRoomEncryptionBackend::Lime);
std::shared_ptr<linphone::ChatRoom> chatRoom = core->createChatRoom(params, localAddress, participants);
/*
if( chatRoom!=nullptr){
auto search = core->searchChatRoom(params, localAddress
, address
, participants);
if(search != chatRoom)
qWarning("toto");
}
return chatRoom!=nullptr;
*/
return false;
}
// -----------------------------------------------------------------------------
int CallsListModel::getRunningCallsNumber () const {

View file

@ -44,6 +44,7 @@ public:
Q_INVOKABLE void launchAudioCall (const QString &sipAddress, const QHash<QString, QString> &headers = {}) const;
Q_INVOKABLE void launchVideoCall (const QString &sipAddress) const;
Q_INVOKABLE bool launchSecureChat (const QString &sipAddress) const;
Q_INVOKABLE int getRunningCallsNumber () const;

View file

@ -309,13 +309,58 @@ private:
// -----------------------------------------------------------------------------
ChatModel::ChatModel (const QString &peerAddress, const QString &localAddress) {
ChatModel::ChatModel (const QString &peerAddress, const QString &localAddress, const bool& isSecure) {
CoreManager *coreManager = CoreManager::getInstance();
mCoreHandlers = coreManager->getHandlers();
mMessageHandlers = make_shared<MessageHandlers>(this);
setSipAddresses(peerAddress, localAddress);
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
shared_ptr<linphone::Factory> factory(linphone::Factory::get());
std::shared_ptr<linphone::ChatRoomParams> params = core->createDefaultChatRoomParams();
std::list<std::shared_ptr<linphone::Address>> participants;
//params->enableEncryption(isSecure);
//if(isSecure){
// params->setBackend(linphone::ChatRoomBackend::FlexisipChat);
// params->setEncryptionBackend(linphone::ChatRoomEncryptionBackend::Lime);
// }
mChatRoom = core->searchChatRoom(params, factory->createAddress(localAddress.toStdString())
, factory->createAddress(peerAddress.toStdString())
, participants);
/*
mChatRoom = core->getChatRoom(
factory->createAddress(peerAddress.toStdString()),
factory->createAddress(localAddress.toStdString())
);*/
Q_ASSERT(mChatRoom);
handleIsComposingChanged(mChatRoom);
// Get messages.
mEntries.clear();
QElapsedTimer timer;
timer.start();
for (auto &message : mChatRoom->getHistory(0))
mEntries << qMakePair(
QVariantMap{
{ "type", EntryType::MessageEntry },
{ "timestamp", QDateTime::fromMSecsSinceEpoch(message->getTime() * 1000) }
},
static_pointer_cast<void>(message)
);
// Get calls.
if(!getIsSecure() )
for (auto &callLog : core->getCallHistory(mChatRoom->getPeerAddress(), mChatRoom->getLocalAddress()))
insertCall(callLog);
qInfo() << QStringLiteral("ChatModel (%1, %2) loaded in %3 milliseconds.")
.arg(peerAddress).arg(localAddress).arg(timer.elapsed());
// Rebind lost handlers
for(auto i = mEntries.begin() ; i != mEntries.end() ; ++i){
if(i->first["type"] == EntryType::MessageEntry){
@ -330,7 +375,67 @@ ChatModel::ChatModel (const QString &peerAddress, const QString &localAddress) {
QObject::connect(coreHandlers, &CoreHandlers::callStateChanged, this, &ChatModel::handleCallStateChanged);
QObject::connect(coreHandlers, &CoreHandlers::isComposingChanged, this, &ChatModel::handleIsComposingChanged);
}
if(!mChatRoom)
qWarning("TOTO A");
}
ChatModel::ChatModel (std::shared_ptr<linphone::ChatRoom> chatRoom){
CoreManager *coreManager = CoreManager::getInstance();
mCoreHandlers = coreManager->getHandlers();
mMessageHandlers = make_shared<MessageHandlers>(this);
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
shared_ptr<linphone::Factory> factory(linphone::Factory::get());
std::shared_ptr<linphone::ChatRoomParams> params = core->createDefaultChatRoomParams();
std::list<std::shared_ptr<linphone::Address>> participants;
mChatRoom = chatRoom;
Q_ASSERT(mChatRoom);
handleIsComposingChanged(mChatRoom);
// Get messages.
mEntries.clear();
QElapsedTimer timer;
timer.start();
for (auto &message : mChatRoom->getHistory(0))
mEntries << qMakePair(
QVariantMap{
{ "type", EntryType::MessageEntry },
{ "timestamp", QDateTime::fromMSecsSinceEpoch(message->getTime() * 1000) }
},
static_pointer_cast<void>(message)
);
// Get calls.
if(!getIsSecure() )
for (auto &callLog : core->getCallHistory(mChatRoom->getPeerAddress(), mChatRoom->getLocalAddress()))
insertCall(callLog);
// Rebind lost handlers
for(auto i = mEntries.begin() ; i != mEntries.end() ; ++i){
if(i->first["type"] == EntryType::MessageEntry){
shared_ptr<linphone::ChatMessage> message = static_pointer_cast<linphone::ChatMessage>(i->second);
message->removeListener(mMessageHandlers);// Remove old listener if already exists
message->addListener(mMessageHandlers);
}
}
{
CoreHandlers *coreHandlers = mCoreHandlers.get();
QObject::connect(coreHandlers, &CoreHandlers::messageReceived, this, &ChatModel::handleMessageReceived);
QObject::connect(coreHandlers, &CoreHandlers::callStateChanged, this, &ChatModel::handleCallStateChanged);
QObject::connect(coreHandlers, &CoreHandlers::isComposingChanged, this, &ChatModel::handleIsComposingChanged);
}
if(!mChatRoom)
qWarning("TOTO B");
}
ChatModel::~ChatModel () {
@ -407,20 +512,34 @@ QString ChatModel::getLocalAddress () const {
);
}
QString ChatModel::getFullPeerAddress () const {
if(!mChatRoom)
qWarning("TOTO Z");
return QString::fromStdString(mChatRoom->getPeerAddress()->asString());
}
QString ChatModel::getFullLocalAddress () const {
return QString::fromStdString(mChatRoom->getLocalAddress()->asString());
}
void ChatModel::setSipAddresses (const QString &peerAddress, const QString &localAddress) {
void ChatModel::setSipAddresses (const QString &peerAddress, const QString &localAddress, const bool& isSecure) {
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
shared_ptr<linphone::Factory> factory(linphone::Factory::get());
std::shared_ptr<linphone::ChatRoomParams> params = core->createDefaultChatRoomParams();
std::list<std::shared_ptr<linphone::Address>> participants;
//params->enableEncryption(isSecure);
//if(isSecure){
// params->setBackend(linphone::ChatRoomBackend::FlexisipChat);
// params->setEncryptionBackend(linphone::ChatRoomEncryptionBackend::Lime);
// }
mChatRoom = core->searchChatRoom(params, factory->createAddress(localAddress.toStdString())
, factory->createAddress(peerAddress.toStdString())
, participants);
/*
mChatRoom = core->getChatRoom(
factory->createAddress(peerAddress.toStdString()),
factory->createAddress(localAddress.toStdString())
);
);*/
Q_ASSERT(mChatRoom);
handleIsComposingChanged(mChatRoom);
@ -441,14 +560,23 @@ void ChatModel::setSipAddresses (const QString &peerAddress, const QString &loca
);
// Get calls.
for (auto &callLog : core->getCallHistory(mChatRoom->getPeerAddress(), mChatRoom->getLocalAddress()))
insertCall(callLog);
if(!getIsSecure() )
for (auto &callLog : core->getCallHistory(mChatRoom->getPeerAddress(), mChatRoom->getLocalAddress()))
insertCall(callLog);
qInfo() << QStringLiteral("ChatModel (%1, %2) loaded in %3 milliseconds.")
.arg(peerAddress).arg(localAddress).arg(timer.elapsed());
if(!mChatRoom)
qWarning("TOTO C");
}
bool ChatModel::getIsSecure() const{
return mChatRoom->getSecurityLevel() == linphone::ChatRoomSecurityLevel::Encrypted
|| mChatRoom->getSecurityLevel() == linphone::ChatRoomSecurityLevel::Safe;
}
bool ChatModel::getIsRemoteComposing () const {
return mIsRemoteComposing;
}
@ -637,7 +765,9 @@ void ChatModel::resetMessageCount () {
}
emit messageCountReset();
}
std::shared_ptr<linphone::ChatRoom> ChatModel::getChatRoom(){
return mChatRoom;
}
// -----------------------------------------------------------------------------
const ChatModel::ChatEntryData ChatModel::getFileMessageEntry (int id) {

View file

@ -73,7 +73,8 @@ public:
};
Q_ENUM(MessageStatus);
ChatModel (const QString &peerAddress, const QString &localAddress);
ChatModel (const QString &peerAddress, const QString &localAddress, const bool& isSecure);
ChatModel (std::shared_ptr<linphone::ChatRoom> chatRoom);
~ChatModel ();
int rowCount (const QModelIndex &index = QModelIndex()) const override;
@ -88,6 +89,8 @@ public:
QString getLocalAddress () const;
QString getFullPeerAddress () const;
QString getFullLocalAddress () const;
bool getIsSecure() const;
bool getIsRemoteComposing () const;
@ -111,6 +114,8 @@ public:
void compose ();
void resetMessageCount ();
std::shared_ptr<linphone::ChatRoom> getChatRoom();
signals:
bool isRemoteComposingChanged (bool status);
@ -128,7 +133,7 @@ signals:
private:
typedef QPair<QVariantMap, std::shared_ptr<void>> ChatEntryData;
void setSipAddresses (const QString &peerAddress, const QString &localAddress);
void setSipAddresses (const QString &peerAddress, const QString &localAddress, const bool& isSecure);
const ChatEntryData getFileMessageEntry (int id);
@ -144,10 +149,13 @@ private:
bool mIsRemoteComposing = false;
mutable QList<ChatEntryData> mEntries;
std::shared_ptr<linphone::ChatRoom> mChatRoom;
std::shared_ptr<CoreHandlers> mCoreHandlers;
std::shared_ptr<MessageHandlers> mMessageHandlers;
std::shared_ptr<linphone::ChatRoom> mChatRoom;
};
Q_DECLARE_METATYPE(std::shared_ptr<ChatModel>);
#endif // CHAT_MODEL_H_

View file

@ -64,6 +64,7 @@ private:
ChatProxyModel::ChatProxyModel (QObject *parent) : QSortFilterProxyModel(parent) {
setSourceModel(new ChatModelFilter(this));
mIsSecure = false;
App *app = App::getInstance();
QObject::connect(app->getMainWindow(), &QWindow::activeChanged, this, [this]() {
@ -168,7 +169,7 @@ QString ChatProxyModel::getPeerAddress () const {
void ChatProxyModel::setPeerAddress (const QString &peerAddress) {
mPeerAddress = peerAddress;
reload();
//reload();
}
QString ChatProxyModel::getLocalAddress () const {
@ -177,7 +178,7 @@ QString ChatProxyModel::getLocalAddress () const {
void ChatProxyModel::setLocalAddress (const QString &localAddress) {
mLocalAddress = localAddress;
reload();
//reload();
}
QString ChatProxyModel::getFullPeerAddress () const {
@ -198,6 +199,14 @@ void ChatProxyModel::setFullLocalAddress (const QString &localAddress) {
//reload();
}
int ChatProxyModel::getIsSecure () const {
return mChatModel ? mChatModel->getIsSecure() : -1;
}
void ChatProxyModel::setIsSecure (const int &secure) {
mIsSecure = secure;
}
bool ChatProxyModel::getIsRemoteComposing () const {
return mChatModel ? mChatModel->getIsRemoteComposing() : false;
}
@ -218,7 +227,10 @@ void ChatProxyModel::reload () {
QObject::disconnect(chatModel, &ChatModel::messageSent, this, &ChatProxyModel::handleMessageSent);
}
mChatModel = CoreManager::getInstance()->getChatModel(mPeerAddress, mLocalAddress);
//mChatModel = CoreManager::getInstance()->getChatModel(mPeerAddress, mLocalAddress, mIsSecure);
//if(mChatRoom)
mChatModel = CoreManager::getInstance()->getChatModel(mChatRoom);
if (mChatModel) {
@ -235,6 +247,16 @@ void ChatProxyModel::resetMessageCount(){
mChatModel->resetMessageCount();
}
}
std::shared_ptr<ChatModel> ChatProxyModel::getChatRoom () const{
return mChatModel;
}
void ChatProxyModel::setChatRoom (std::shared_ptr<ChatModel> chatModel){
mChatRoom = chatModel->getChatRoom();
reload();
emit chatRoomChanged();
}
// -----------------------------------------------------------------------------
static inline QWindow *getParentWindow (QObject *object) {

View file

@ -38,7 +38,11 @@ class ChatProxyModel : public QSortFilterProxyModel {
Q_PROPERTY(QString localAddress READ getLocalAddress WRITE setLocalAddress NOTIFY localAddressChanged);
Q_PROPERTY(QString fullPeerAddress READ getFullPeerAddress WRITE setFullPeerAddress NOTIFY fullPeerAddressChanged);
Q_PROPERTY(QString fullLocalAddress READ getFullLocalAddress WRITE setFullLocalAddress NOTIFY fullLocalAddressChanged);
Q_PROPERTY(int isSecure READ getIsSecure WRITE setIsSecure NOTIFY isSecureChanged);
Q_PROPERTY(std::shared_ptr<ChatModel> chatRoom READ getChatRoom WRITE setChatRoom NOTIFY chatRoomChanged);
//Q_PROPERTY(bool isSecure MEMBER mIsSecure NOTIFY isSecureChanged);
Q_PROPERTY(bool isRemoteComposing READ getIsRemoteComposing NOTIFY isRemoteComposingChanged);
//Q_PROPERTY(bool isSecure READ getIsSecure NOTIFY isSecureChanged);
Q_PROPERTY(QString cachedText READ getCachedText);
public:
@ -62,13 +66,16 @@ public:
Q_INVOKABLE void compose (const QString& text);
Q_INVOKABLE void resetMessageCount();
signals:
void peerAddressChanged (const QString &peerAddress);
void localAddressChanged (const QString &localAddress);
void fullPeerAddressChanged (const QString &fullPeerAddress);
void fullLocalAddressChanged (const QString &fullLocalAddress);
bool isRemoteComposingChanged (bool status);
bool isSecureChanged(bool secure);
void chatRoomChanged();
void moreEntriesLoaded (int n);
@ -89,6 +96,12 @@ private:
QString getFullLocalAddress () const;
void setFullLocalAddress (const QString &localAddress);
int getIsSecure () const;
void setIsSecure (const int &secure);
std::shared_ptr<ChatModel> getChatRoom () const;
void setChatRoom (std::shared_ptr<ChatModel> chatRoom);
bool getIsRemoteComposing () const;
@ -108,7 +121,10 @@ private:
QString mLocalAddress;
QString mFullPeerAddress;
QString mFullLocalAddress;
int mIsSecure;
static QString gCachedText;
std::shared_ptr<linphone::ChatRoom> mChatRoom;
std::shared_ptr<ChatModel> mChatModel;

View file

@ -196,7 +196,9 @@ void CoreHandlers::onMessageReceived (
!app->hasFocus() ||
!CoreManager::getInstance()->chatModelExists(
Utils::coreStringToAppString(chatRoom->getPeerAddress()->asStringUriOnly()),
Utils::coreStringToAppString(chatRoom->getLocalAddress()->asStringUriOnly())
Utils::coreStringToAppString(chatRoom->getLocalAddress()->asStringUriOnly()),
chatRoom->getSecurityLevel() == linphone::ChatRoomSecurityLevel::Encrypted
|| chatRoom->getSecurityLevel() == linphone::ChatRoomSecurityLevel::Safe
)
)
core->playLocal(Utils::appStringToCoreString(settingsModel->getChatNotificationSoundPath()));

View file

@ -38,6 +38,7 @@
#include "components/settings/AccountSettingsModel.hpp"
#include "components/settings/SettingsModel.hpp"
#include "components/sip-addresses/SipAddressesModel.hpp"
#include "components/timeline/TimelineListModel.hpp"
#include "utils/Utils.hpp"
@ -106,6 +107,7 @@ void CoreManager::initCoreManager(){
mSettingsModel = new SettingsModel(this);
mSipAddressesModel = new SipAddressesModel(this);
mEventCountNotifier = new EventCountNotifier(this);
mTimelineListModel = new TimelineListModel(this);
mEventCountNotifier->updateUnreadMessageCount();
QObject::connect(mEventCountNotifier, &EventCountNotifier::eventCountChanged,this, &CoreManager::eventCountChanged);
migrate();
@ -118,12 +120,12 @@ CoreManager *CoreManager::getInstance (){
return mInstance;
}
shared_ptr<ChatModel> CoreManager::getChatModel (const QString &peerAddress, const QString &localAddress) {
shared_ptr<ChatModel> CoreManager::getChatModel (const QString &peerAddress, const QString &localAddress, const bool& isSecure) {
if (peerAddress.isEmpty() || localAddress.isEmpty())
return nullptr;
// Create a new chat model.
QPair<QString, QString> chatModelId{ peerAddress, localAddress };
QPair<bool, QPair<QString, QString>> chatModelId{isSecure,{ peerAddress, localAddress }};
if (!mChatModels.contains(chatModelId)) {
if (
!mCore->createAddress(peerAddress.toStdString()) ||
@ -140,7 +142,7 @@ shared_ptr<ChatModel> CoreManager::getChatModel (const QString &peerAddress, con
delete chatModel;
};
shared_ptr<ChatModel> chatModel(new ChatModel(peerAddress, localAddress), deleter);
shared_ptr<ChatModel> chatModel(new ChatModel(peerAddress, localAddress, isSecure), deleter);
mChatModels[chatModelId] = chatModel;
emit chatModelCreated(chatModel);
@ -154,8 +156,46 @@ shared_ptr<ChatModel> CoreManager::getChatModel (const QString &peerAddress, con
return chatModel;
}
bool CoreManager::chatModelExists (const QString &peerAddress, const QString &localAddress) {
return mChatModels.contains({ peerAddress, localAddress });
shared_ptr<ChatModel> CoreManager::getChatModel (std::shared_ptr<linphone::ChatRoom> chatRoom) {
if (!chatRoom)
return nullptr;
auto pc = chatRoom->getCurrentParams();
for(auto it = mChatModels.begin() ; it != mChatModels.end() ; ++it) {
auto a = it->lock();
auto pa = a->getChatRoom()->getCurrentParams();
if( a->getChatRoom()->getConferenceAddress() == chatRoom->getConferenceAddress()
&& a->getChatRoom()->getLocalAddress() == chatRoom->getLocalAddress()
&& a->getChatRoom()->getPeerAddress() == chatRoom->getPeerAddress()
&& a->getChatRoom()->getPeerAddress() == chatRoom->getPeerAddress()
&& pa->encryptionEnabled() == pc->encryptionEnabled()
){
// Returns an existing chat model.
shared_ptr<ChatModel> chatModel = a;
Q_CHECK_PTR(chatModel);
return chatModel;
}
}
QPair<bool, QPair<QString, QString>> chatModelId{pc->encryptionEnabled(),
{ QString::fromStdString(chatRoom->getPeerAddress()->asString())
, QString::fromStdString(chatRoom->getLocalAddress()->asString()) }};
auto deleter = [this, chatModelId](ChatModel *chatModel) {
bool removed = mChatModels.remove(chatModelId);
Q_ASSERT(removed);
chatModel->deleteLater();
};
shared_ptr<ChatModel> chatModel(new ChatModel(chatRoom), deleter);
mChatModels[chatModelId] = chatModel;
emit chatModelCreated(chatModel);
return chatModel;
}
bool CoreManager::chatModelExists (const QString &peerAddress, const QString &localAddress, const bool &isSecure) {
return mChatModels.contains({isSecure, { peerAddress, localAddress}});
}
HistoryModel* CoreManager::getHistoryModel(){
@ -275,6 +315,12 @@ void CoreManager::createLinphoneCore (const QString &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);

View file

@ -43,6 +43,7 @@ class LdapListModel;
class SettingsModel;
class SipAddressesModel;
class VcardModel;
class TimelineListModel;
class CoreManager : public QObject {
@ -66,8 +67,9 @@ public:
return mHandlers;
}
std::shared_ptr<ChatModel> getChatModel (const QString &peerAddress, const QString &localAddress);
bool chatModelExists (const QString &sipAddress, const QString &localAddress);
std::shared_ptr<ChatModel> getChatModel (const QString &peerAddress, const QString &localAddress, const bool &isSecure);
std::shared_ptr<ChatModel> getChatModel (std::shared_ptr<linphone::ChatRoom> chatRoom);
bool chatModelExists (const QString &sipAddress, const QString &localAddress, const bool &isSecure);
HistoryModel* getHistoryModel();
@ -101,8 +103,11 @@ public:
Q_CHECK_PTR(mContactsImporterListModel);
return mContactsImporterListModel;
}
TimelineListModel *getTimelineListModel () const {
Q_CHECK_PTR(mTimelineListModel);
return mTimelineListModel;
}
SipAddressesModel *getSipAddressesModel () const {
Q_CHECK_PTR(mSipAddressesModel);
@ -194,6 +199,7 @@ private:
CallsListModel *mCallsListModel = nullptr;
ContactsListModel *mContactsListModel = nullptr;
ContactsImporterListModel *mContactsImporterListModel = nullptr;
TimelineListModel *mTimelineListModel = nullptr;
SipAddressesModel *mSipAddressesModel = nullptr;
SettingsModel *mSettingsModel = nullptr;
@ -201,7 +207,7 @@ private:
EventCountNotifier *mEventCountNotifier = nullptr;
QHash<QPair<QString, QString>, std::weak_ptr<ChatModel>> mChatModels;
QHash<QPair<bool, QPair<QString, QString> >, std::weak_ptr<ChatModel>> mChatModels;
HistoryModel * mHistoryModel = nullptr;
LdapListModel *mLdapListModel = nullptr;

View file

@ -0,0 +1,148 @@
/*
* 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 "TimelineListModel.hpp"
#include "TimelineModel.hpp"
#include <QDebug>
// =============================================================================
TimelineListModel::TimelineListModel (QObject *parent) : QAbstractListModel(parent) {
initTimeline();
}
// -----------------------------------------------------------------------------
void TimelineListModel::reset(){
initTimeline();
}
int TimelineListModel::rowCount (const QModelIndex &) const {
return mTimelines.count();
}
QHash<int, QByteArray> TimelineListModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$timelines";
return roles;
}
QVariant TimelineListModel::data (const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mTimelines.count())
return QVariant();
if (role == Qt::DisplayRole)
return QVariant::fromValue(mTimelines[row]);
return QVariant();
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
bool TimelineListModel::removeRow (int row, const QModelIndex &parent) {
return removeRows(row, 1, parent);
}
bool TimelineListModel::removeRows (int row, int count, const QModelIndex &parent) {
int limit = row + count - 1;
if (row < 0 || count < 0 || limit >= mTimelines.count())
return false;
beginRemoveRows(parent, row, limit);
for (int i = 0; i < count; ++i)
delete mTimelines.takeAt(row);
endRemoveRows();
return true;
}
// -----------------------------------------------------------------------------
void TimelineListModel::initTimeline () {
CoreManager *coreManager = CoreManager::getInstance();
auto currentAddress = coreManager->getAccountSettingsModel()->getUsedSipAddress();
std::list<std::shared_ptr<linphone::ChatRoom>> allChatRooms = coreManager->getCore()->getChatRooms();
QList<TimelineModel*> models;
for(auto itAllChatRooms = allChatRooms.begin() ; itAllChatRooms != allChatRooms.end() ; ++itAllChatRooms){
if((*itAllChatRooms)->getMe()->getAddress()->weakEqual(currentAddress)){
models << new TimelineModel(*itAllChatRooms);
}
}
//beginInsertRows(QModelIndex(), 0, models.count()-1);
mTimelines = models;
//endInsertRows();
/*
initSipAddressesFromChat();
initSipAddressesFromCalls();
initRefs();
initSipAddressesFromContacts();*/
/*
auto bcSections = lConfig->getSectionsNamesList();
// Loop on all sections and load configuration. If this is not a LDAP configuration, the model is discarded.
for(auto itSections = bcSections.begin(); itSections != bcSections.end(); ++itSections) {
TimelineModel * model = new TimelineModel();
if(model->load(*itSections)){
mTimelines.append(model);
}else
delete model;
}
*/
}
/*
// Create a new TimelineModel and put it in the list
void TimelineListModel::add(){
int row = mTimelines.count();
beginInsertRows(QModelIndex(), row, row);
auto model = new TimelineModel();
model->init();
mTimelines << model;
endInsertRows();
resetInternalData();
}
*/
void TimelineListModel::remove (TimelineModel *model) {
/*
int index = mTimelines.indexOf(ldap);
if (index >=0){
ldap->unsave();
removeRow(index);
}*/
}

View file

@ -0,0 +1,54 @@
/*
* 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_LIST_MODEL_H_
#define TIMELINE_LIST_MODEL_H_
#include <QSortFilterProxyModel>
class TimelineModel;
// =============================================================================
class TimelineListModel : public QAbstractListModel {
Q_OBJECT
public:
TimelineListModel (QObject *parent = Q_NULLPTR);
void reset();
int rowCount (const QModelIndex &index = QModelIndex()) const override;
QHash<int, QByteArray> roleNames () const override;
QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
// Remove a chatroom
Q_INVOKABLE void remove (TimelineModel *importer);
private:
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
void initTimeline ();
QList<TimelineModel*> mTimelines;
};
#endif // TIMELINE_LIST_MODEL_H_

View file

@ -0,0 +1,102 @@
/*
* 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

@ -0,0 +1,54 @@
/*
* 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

@ -21,6 +21,7 @@
#include "components/core/CoreManager.hpp"
#include "components/settings/AccountSettingsModel.hpp"
#include "components/sip-addresses/SipAddressesModel.hpp"
#include "components/chat/ChatModel.hpp"
#include "utils/Utils.hpp"
#include "TimelineModel.hpp"
@ -30,73 +31,40 @@
// =============================================================================
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);
TimelineModel::TimelineModel (std::shared_ptr<linphone::ChatRoom> chatRoom, QObject *parent) : QObject(parent) {
mChatModel = CoreManager::getInstance()->getChatModel(chatRoom);
}
QHash<int, QByteArray> TimelineModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$timelineEntry";
return roles;
QString TimelineModel::getFullPeerAddress() const{
return mChatModel->getFullPeerAddress();
}
QString TimelineModel::getFullLocalAddress() const{
return mChatModel->getLocalAddress();
}
// -----------------------------------------------------------------------------
static inline const QHash<QString, SipAddressesModel::ConferenceEntry> *getLocalToConferenceEntry (const QVariantMap &map) {
return map.value("__localToConferenceEntry").value<decltype(getLocalToConferenceEntry({}))>();
QString TimelineModel::getUsername() const{
std::string username = mChatModel->getChatRoom()->getSubject();
if(username != ""){
return QString::fromStdString(username);
}
username = mChatModel->getChatRoom()->getPeerAddress()->getDisplayName();
if(username != "")
return QString::fromStdString(username);
username = mChatModel->getChatRoom()->getPeerAddress()->getUsername();
if(username != "")
return QString::fromStdString(username);
return QString::fromStdString(mChatModel->getChatRoom()->getPeerAddress()->asStringUriOnly());
}
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;
QString TimelineModel::getAvatar() const{
return "";
}
bool TimelineModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const {
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
return getLocalToConferenceEntry(index.data().toMap())->contains(getCleanedLocalAddress());
int TimelineModel::getPresenceStatus() const{
return 0;
}
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();
}
std::shared_ptr<ChatModel> TimelineModel::getChatRoom() const{
return mChatModel;
}

View file

@ -23,32 +23,53 @@
#include <QSortFilterProxyModel>
// =============================================================================
#include <QObject>
#include <QDateTime>
class TimelineModel : public QSortFilterProxyModel {
Q_OBJECT;
#include <linphone++/chat_room.hh>
Q_PROPERTY(QString localAddress READ getLocalAddress NOTIFY localAddressChanged);
#include "../contact/ContactModel.hpp"
class ChatModel;
class TimelineModel : public QObject {
Q_OBJECT
public:
TimelineModel (QObject *parent = Q_NULLPTR);
TimelineModel (std::shared_ptr<linphone::ChatRoom> chatRoom, QObject *parent = Q_NULLPTR);
Q_PROPERTY(QString fullPeerAddress READ getFullPeerAddress NOTIFY fullPeerAddressChanged)
Q_PROPERTY(QString fullLocalAddress READ getFullLocalAddress NOTIFY fullLocalAddressChanged)
Q_PROPERTY(std::shared_ptr<ChatModel> chatRoom READ getChatRoom CONSTANT)
// Contact
Q_PROPERTY(QString sipAddress READ getFullPeerAddress NOTIFY fullPeerAddressChanged)
Q_PROPERTY(QString username READ getUsername NOTIFY usernameChanged)
Q_PROPERTY(QString avatar READ getAvatar NOTIFY avatarChanged)
Q_PROPERTY(int presenceStatus READ getPresenceStatus NOTIFY presenceStatusChanged)
QString getFullPeerAddress() const;
QString getFullLocalAddress() const;
QString getUsername() const;
QString getAvatar() const;
int getPresenceStatus() const;
std::shared_ptr<ChatModel> getChatRoom() const;
QHash<int, QByteArray> roleNames () const override;
QDateTime mTimestamp;
std::shared_ptr<ChatModel> mChatModel;
//std::shared_ptr<linphone::ChatRoom> mChatRoom;
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;
void fullPeerAddressChanged();
void fullLocalAddressChanged();
void usernameChanged();
void avatarChanged();
void presenceStatusChanged();
};
#endif // TIMELINE_MODEL_H_

View file

@ -0,0 +1,54 @@
/*
* 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 "TimelineProxyModel.hpp"
#include "TimelineListModel.hpp"
#include "TimelineModel.hpp"
#include <QDebug>
// =============================================================================
// -----------------------------------------------------------------------------
TimelineProxyModel::TimelineProxyModel (QObject *parent) : QSortFilterProxyModel(parent) {
setSourceModel(CoreManager::getInstance()->getTimelineListModel());
sort(0);
}
// -----------------------------------------------------------------------------
bool TimelineProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const {
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
return true;
}
bool TimelineProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
const TimelineModel* a = sourceModel()->data(left).value<TimelineModel*>();
const TimelineModel* b = sourceModel()->data(right).value<TimelineModel*>();
return a->mTimestamp <= b->mTimestamp;
}

View file

@ -0,0 +1,45 @@
/*
* 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_PROXY_MODEL_H_
#define TIMELINE_PROXY_MODEL_H_
#include <QSortFilterProxyModel>
// =============================================================================
class TimelineProxyModel : public QSortFilterProxyModel {
Q_OBJECT;
public:
TimelineProxyModel (QObject *parent = Q_NULLPTR);
protected:
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);
};
#endif // TIMELINE_PROXY_MODEL_H_

View file

@ -19,8 +19,9 @@ Rectangle {
// A entry from `SipAddressesModel` or an `SipAddressObserver`.
property var entry
// entry should have these functions : presenceStatus, sipAddress, username, avatar (image)
readonly property var _contact: entry.contact
//readonly property var _contact: entry.contact
// ---------------------------------------------------------------------------
@ -41,13 +42,15 @@ Rectangle {
Layout.preferredHeight: ContactStyle.contentHeight
Layout.preferredWidth: ContactStyle.contentHeight
image: _contact && _contact.vcard.avatar
//image: _contact && _contact.vcard.avatar
image: entry.avatar
presenceLevel: entry.presenceStatus != null
? Presence.getPresenceLevel(entry.presenceStatus)
: -1
username: LinphoneUtils.getContactUsername(_contact || entry.sipAddress || entry.fullPeerAddress || entry.peerAddress || '')
//username: LinphoneUtils.getContactUsername(_contact || entry.sipAddress || entry.fullPeerAddress || entry.peerAddress || '')
username: entry.username
}
ContactDescription {
@ -57,7 +60,8 @@ Rectangle {
Layout.fillWidth: true
Layout.leftMargin: ContactStyle.spacing
sipAddress: entry.sipAddress || entry.fullPeerAddress || entry.peerAddress || ''
//sipAddress: entry.sipAddress || entry.fullPeerAddress || entry.peerAddress || ''
sipAddress: entry.sipAddress
username: avatar.username
}

View file

@ -26,6 +26,7 @@
// =============================================================================
function setSelectedEntry (peerAddress, localAddress) {
/*
if (localAddress != null && localAddress !== Linphone.AccountSettingsModel.sipAddress) {
resetSelectedEntry()
return
@ -42,16 +43,19 @@ function setSelectedEntry (peerAddress, localAddress) {
return
}
}
*/
}
function resetSelectedEntry () {
/*
view.currentIndex = -1
timeline._selectedSipAddress = ''
timeline._selectedSipAddress = ''*/
}
// -----------------------------------------------------------------------------
function handleDataChanged (topLeft, bottomRight, roles) {
/*
var index = view.currentIndex
var model = timeline.model
var sipAddress = timeline._selectedSipAddress
@ -62,18 +66,22 @@ function handleDataChanged (topLeft, bottomRight, roles) {
) {
setSelectedEntry(sipAddress)
}
*/
}
function handleRowsAboutToBeRemoved (parent, first, last) {
/*
var index = view.currentIndex
if (index >= first && index <= last) {
view.currentIndex = -1
}
*/
}
function handleCountChanged (_) {
/*
var sipAddress = timeline._selectedSipAddress
if (sipAddress.length > 0) {
setSelectedEntry(sipAddress)
}
}*/
}

View file

@ -19,7 +19,8 @@ Rectangle {
// ---------------------------------------------------------------------------
signal entrySelected (string entry)
//signal entrySelected (string entry)
signal entrySelected (TimelineModel entry)
// ---------------------------------------------------------------------------
@ -62,7 +63,7 @@ Rectangle {
anchors.fill:parent
onClicked: {
view.currentIndex = -1
timeline.entrySelected('')
timeline.entrySelected('',false)
}
}
@ -117,7 +118,9 @@ Rectangle {
: TimelineStyle.contact.backgroundColor.b
)
displayUnreadMessageCount: SettingsModel.chatEnabled
entry: $timelineEntry
//entry: $timelineEntry
//entry: SipAddressesModel.getSipAddressObserver(modelData.fullPeerAddress, modelData.fullLocalAddress)
entry: modelData
sipAddressColor: isSelected
? TimelineStyle.contact.sipAddress.color.selected
: TimelineStyle.contact.sipAddress.color.normal
@ -128,10 +131,11 @@ Rectangle {
Loader {
anchors.fill: parent
sourceComponent: TooltipArea {
text: $timelineEntry.timestamp.toLocaleString(
Qt.locale(App.locale),
Locale.ShortFormat
)
//text: $timelineEntry.timestamp.toLocaleString(
//Qt.locale(App.locale),
//Locale.ShortFormat
//)
}
}
}
@ -140,7 +144,8 @@ Rectangle {
anchors.fill: parent
onClicked: {
view.currentIndex = index
timeline.entrySelected($timelineEntry.sipAddress)
timeline.entrySelected(modelData)
//timeline.entrySelected($timelineEntry.sipAddress, $timelineEntry.isSecure)
}
}
}

View file

@ -148,6 +148,11 @@ ColumnLayout {
icon: SettingsModel.chatEnabled && SettingsModel.showStartChatButton ? 'chat' : 'history'
onClicked: actions.itemAt(2).open()
}
ActionButton {
icon: 'call_chat_unsecure'
onClicked: {console.log("A");actions.itemAt(3).open()}
}
}
ActionButton {
@ -176,8 +181,23 @@ ColumnLayout {
peerAddress: sipAddress,
localAddress: AccountSettingsModel.sipAddress,
fullPeerAddress: sipAddress,
fullLocalAddress: AccountSettingsModel.fullSipAddress
fullLocalAddress: AccountSettingsModel.fullSipAddress,
secure:false
})
},
function (sipAddress) {
console.log("B")
if(CallsListModel.launchSecureChat(sipAddress)){
console.log("C")
window.setView('Conversation', {
peerAddress: sipAddress,
localAddress: AccountSettingsModel.sipAddress,
fullPeerAddress: sipAddress,
fullLocalAddress: AccountSettingsModel.fullSipAddress,
secure:true
})
}else
console.log("D")
}
]

View file

@ -17,6 +17,8 @@ ColumnLayout {
property string localAddress
property string fullPeerAddress
property string fullLocalAddress
property int isSecure
property var chatRoom
readonly property var _sipAddressObserver: SipAddressesModel.getSipAddressObserver((fullPeerAddress?fullPeerAddress:peerAddress), (fullLocalAddress?fullLocalAddress:localAddress))
@ -170,11 +172,13 @@ ColumnLayout {
}
resetMessageCount()
}
isSecure: conversation.isSecure
chatRoom: conversation.chatRoom
peerAddress: conversation.peerAddress
localAddress: conversation.localAddress
fullPeerAddress: conversation.fullPeerAddress
fullLocalAddress: conversation.fullLocalAddress
localAddress: conversation.localAddress// Reload is done on localAddress. Use this order
}
}

View file

@ -160,20 +160,23 @@ ApplicationWindow {
window.setView('ContactEdit', { sipAddress: entry.sipAddress })
} else {
window.setView('Conversation', {
isSecure: entry.isSecure,
peerAddress: entry.sipAddress,
localAddress: AccountSettingsModel.sipAddress,
fullPeerAddress: entry.fullSipAddress,
fullLocalAddress: AccountSettingsModel.fullSipAddress
fullLocalAddress: AccountSettingsModel.fullSipAddress,
localAddress: AccountSettingsModel.sipAddress
})
}
}
onLaunchCall: CallsListModel.launchAudioCall(sipAddress)
onLaunchChat: window.setView('Conversation', {
isSecure:false,
peerAddress: sipAddress,
localAddress: AccountSettingsModel.sipAddress,
fullPeerAddress: sipAddress,
fullLocalAddress: AccountSettingsModel.fullSipAddress
fullLocalAddress: AccountSettingsModel.fullSipAddress,
localAddress: AccountSettingsModel.sipAddress
})
onLaunchVideoCall: CallsListModel.launchVideoCall(sipAddress)
@ -259,13 +262,16 @@ ApplicationWindow {
Layout.fillHeight: true
Layout.fillWidth: true
model: TimelineModel
model: TimelineProxyModel{}
onEntrySelected: (entry?setView('Conversation', {
peerAddress: entry,
localAddress: AccountSettingsModel.sipAddress,
fullPeerAddress: entry,
fullLocalAddress: AccountSettingsModel.fullSipAddress
isSecure:-1,
peerAddress: entry.fullPeerAddress,
fullPeerAddress: entry.fullPeerAddress,
fullLocalAddress: AccountSettingsModel.fullSipAddress,
localAddress: AccountSettingsModel.sipAddress,
chatRoom:entry.chatRoom
}):
setView('HistoryView', {})
)