WARNING: commit to be checked (backup)

Add sanitizer mode.
Fix crashes on QmlEngine.
New ProxyListModel to manage QAbstractListModel.
Fix uninitialized variables.
Replace parent Qt's managment into QSharedPointer for Qt Objects and keep shared_ptr for linphone objects.
Fix OpenH264 Linux URL for 32bits.
Differentiate Qt modelData from app $modelData.
This commit is contained in:
Julien Wadel 2022-04-12 17:26:50 +02:00
parent b893c78399
commit ce5ced320f
70 changed files with 539 additions and 673 deletions

View file

@ -88,6 +88,21 @@ if(ENABLE_BUILD_VERBOSE)
message("LINPHONECXX : ${LINPHONECXX_INCLUDE_DIRS} => ${LINPHONECXX_LIBRARIES}")
endif()
# Build configuration
#############################
#Sanitizer
if(ENABLE_SANITIZER)
set(sanitize_flags "-fsanitize=address,undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls")
set(sanitize_linker_flags "-fsanitize=address,undefined")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${sanitize_flags}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${sanitize_flags}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${sanitize_linker_flags}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${sanitize_linker_flags}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${sanitize_linker_flags}")
endif()
#############################
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG -DQT_NO_DEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DQT_QML_DEBUG -DQT_DECLARATIVE_DEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG -DQT_QML_DEBUG -DQT_DECLARATIVE_DEBUG" )
@ -194,6 +209,7 @@ set(SOURCES
src/components/participant/ParticipantModel.cpp
src/components/participant/ParticipantListModel.cpp
src/components/participant/ParticipantProxyModel.cpp
src/components/participant/ParticipantDeviceListener.cpp
src/components/participant/ParticipantDeviceModel.cpp
src/components/participant/ParticipantDeviceListModel.cpp
src/components/participant/ParticipantDeviceProxyModel.cpp
@ -318,6 +334,7 @@ set(HEADERS
src/components/participant/ParticipantModel.hpp
src/components/participant/ParticipantListModel.hpp
src/components/participant/ParticipantProxyModel.hpp
src/components/participant/ParticipantDeviceListener.hpp
src/components/participant/ParticipantDeviceModel.hpp
src/components/participant/ParticipantDeviceListModel.hpp
src/components/participant/ParticipantDeviceProxyModel.hpp

View file

@ -236,7 +236,8 @@ App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::U
App::~App () {
qInfo() << QStringLiteral("Destroying app...");
if( mEngine )
mEngine->deleteLater();// Let to Qt the time to delete its data
delete mEngine;
processEvents(QEventLoop::AllEvents); // Process all needed events on engine deletion.
if( mParser)
delete mParser;
}
@ -352,7 +353,7 @@ void App::initContentApp () {
// Init engine content.
mEngine = new QQmlApplicationEngine();
mEngine = new QQmlApplicationEngine(this);
// Provide `+custom` folders for custom components and `5.9` for old components.
{

View file

@ -113,8 +113,18 @@ AppController::AppController (int &argc, char *argv[]) {
AppController::~AppController () {
try{
delete mApp;
if(mApp)
delete mApp;
}
catch(...){
}
}
void AppController::stopApp(){
try{
delete mApp;
mApp = nullptr;
}
catch(...){
}
}

View file

@ -34,7 +34,7 @@ public:
Q_CHECK_PTR(mApp);
return mApp;
}
void stopApp();
private:
App *mApp = nullptr;
};

View file

@ -74,6 +74,7 @@ int main (int argc, char *argv[]) {
app->initContentApp();
ret = app->exec();
} while (ret == App::RestartCode);
controller.stopApp(); // Stopping app before core to let time to GUI to process needed items from linphone.
auto core = CoreManager::getInstance()->getCore();
if(core && core->getGlobalState() == linphone::GlobalState::On)
core->stop();

View file

@ -25,15 +25,27 @@
// =============================================================================
ProxyListModel::ProxyListModel (QObject *parent) : QAbstractListModel(parent) {
connect(this, &ProxyListModel::rowsInserted, this, &ProxyListModel::countChanged);
connect(this, &ProxyListModel::rowsRemoved, this, &ProxyListModel::countChanged);
}
ProxyListModel::~ProxyListModel(){
beginResetModel();
mList.clear();
endResetModel();
}
int ProxyListModel::rowCount (const QModelIndex &) const {
return mList.count();
}
int ProxyListModel::getCount() const{
return rowCount();
}
QHash<int, QByteArray> ProxyListModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "modelData";
roles[Qt::DisplayRole] = "$modelData";
return roles;
}
@ -53,6 +65,18 @@ QSharedPointer<QObject> ProxyListModel::getAt(const int& index) const{
return mList[index];
}
QSharedPointer<QObject> ProxyListModel::get(QObject * itemToGet, int * index) const{
int row = 0;
for(auto item : mList)
if( item.get() == itemToGet){
if( index )
*index = row;
return item;
}else
++row;
return nullptr;
}
// -----------------------------------------------------------------------------
void ProxyListModel::add(QSharedPointer<QObject> item){

View file

@ -31,13 +31,23 @@ class ProxyListModel : public QAbstractListModel {
Q_OBJECT
public:
Q_PROPERTY(int count READ getCount NOTIFY countChanged)
ProxyListModel (QObject *parent = Q_NULLPTR);
virtual ~ProxyListModel();
virtual int rowCount (const QModelIndex &index = QModelIndex()) const override;
Q_INVOKABLE int getCount() const;
virtual QHash<int, QByteArray> roleNames () const override;
virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
QSharedPointer<QObject> getAt(const int& index) const;
template <class T>
QSharedPointer<T> getAt(const int& index) const{
return getAt(index).objectCast<T>();
}
QSharedPointer<QObject> get(QObject * itemToGet, int * index = nullptr) const;
template <class T>
QList<QSharedPointer<T>> getSharedList(){
@ -79,6 +89,9 @@ public:
Q_INVOKABLE virtual void resetData();
signals:
void countChanged();
protected:
QList<QSharedPointer<QObject>> mList;

View file

@ -64,7 +64,7 @@ int ConferenceInfoMapModel::rowCount (const QModelIndex &) const {
QHash<int, QByteArray> ConferenceInfoMapModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "modelData";
roles[Qt::DisplayRole] = "$modelData";
roles[Qt::DisplayRole + 1] = "date";
return roles;
}

View file

@ -100,8 +100,6 @@ ChatMessageModel::ChatMessageModel ( std::shared_ptr<linphone::ChatMessage> chat
if( replyMessage)// Reply message could be inexistant (for example : when locally deleted)
mReplyChatMessageModel = create(replyMessage, parent);
}
connect(this, &ChatMessageModel::remove, qobject_cast<ChatRoomModel*>(parent), &ChatRoomModel::removeEntry);
std::list<std::shared_ptr<linphone::Content>> contents = chatMessage->getContents();
QString txt;
for(auto content : contents){

View file

@ -31,6 +31,7 @@
ChatNoticeModel::ChatNoticeModel ( std::shared_ptr<linphone::EventLog> eventLog, QObject * parent) : ChatEvent(ChatRoomModel::EntryType::NoticeEntry, parent) {
App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE
mEventLog = eventLog;
mEventLogType = LinphoneEnums::EventLogType::EventLogTypeNone;
setEventLogType(LinphoneEnums::fromLinphone(mEventLog->getType()));
mTimestamp = QDateTime::fromMSecsSinceEpoch(eventLog->getCreationTime() * 1000);
}

View file

@ -123,7 +123,7 @@ ChatRoomModel::ChatRoomModel (std::shared_ptr<linphone::ChatRoom> chatRoom, QObj
mChatRoom = chatRoom;
mChatRoomListener = std::make_shared<ChatRoomListener>(parent);
connectTo(mChatRoomListener.get());
mChatRoom->addListener(mChatRoomListener);
mChatRoom->addListener(mChatRoomListener);
// Get messages.
mList.clear();
@ -478,7 +478,7 @@ QString ChatRoomModel::getParticipantAddress(){
}else{
auto participants = getParticipants();
if(participants->getCount() > 1)
return participants->getAt(1)->getSipAddress();
return participants->getAt(1).objectCast<ParticipantModel>()->getSipAddress();
else
return "";
}
@ -565,7 +565,7 @@ void ChatRoomModel::enableMarkAsRead(const bool& enable){
void ChatRoomModel::setReply(ChatMessageModel * model){
if(model != mReplyModel.get()){
if( model && model->getChatMessage() )
mReplyModel = ChatMessageModel::create(model->getChatMessage(), this);
mReplyModel = ChatMessageModel::create(model->getChatMessage());
else
mReplyModel = nullptr;
emit replyChanged();
@ -747,19 +747,19 @@ public:
itEntries = entries.begin();
for(; itEntries != entries.end() ; ++itEntries){
if( (*itEntries).mType== ChatRoomModel::EntryType::MessageEntry)
*resultEntries << ChatMessageModel::create(std::dynamic_pointer_cast<linphone::ChatMessage>(itEntries->mObject), chatRoomModel);
*resultEntries << ChatMessageModel::create(std::dynamic_pointer_cast<linphone::ChatMessage>(itEntries->mObject));
else if( (*itEntries).mType == ChatRoomModel::EntryType::CallEntry) {
auto entry = ChatCallModel::create(std::dynamic_pointer_cast<linphone::CallLog>(itEntries->mObject), true, chatRoomModel);
auto entry = ChatCallModel::create(std::dynamic_pointer_cast<linphone::CallLog>(itEntries->mObject), true);
if(entry) {
*resultEntries << entry;
if (entry->mStatus == LinphoneEnums::CallStatusSuccess) {
entry = ChatCallModel::create(entry->getCallLog(), false, chatRoomModel);
entry = ChatCallModel::create(entry->getCallLog(), false);
if(entry)
*resultEntries << entry;
}
}
}else{
auto entry = ChatNoticeModel::create(std::dynamic_pointer_cast<linphone::EventLog>(itEntries->mObject), chatRoomModel);
auto entry = ChatNoticeModel::create(std::dynamic_pointer_cast<linphone::EventLog>(itEntries->mObject));
if(entry) {
*resultEntries << entry;
}
@ -946,6 +946,7 @@ int ChatRoomModel::loadMoreEntries(){
prepareEntries << EntrySorterHelper(eventLog->getCreationTime() , NoticeEntry, eventLog);
}
EntrySorterHelper::getLimitedSelection(&entries, prepareEntries, mLastEntriesStep, this);
if(entries.size() >0){
beginInsertRows(QModelIndex(), 0, entries.size()-1);
for(auto entry : entries)
@ -979,14 +980,14 @@ void ChatRoomModel::callEnded(std::shared_ptr<linphone::Call> call){
void ChatRoomModel::insertCall (const std::shared_ptr<linphone::CallLog> &callLog) {
if(mIsInitialized){
QSharedPointer<ChatCallModel> model = ChatCallModel::create(callLog, true, this);
QSharedPointer<ChatCallModel> model = ChatCallModel::create(callLog, true);
if(model){
int row = mList.count();
beginInsertRows(QModelIndex(), row, row);
mList << model;
endInsertRows();
if (callLog->getStatus() == linphone::Call::Status::Success) {
model = ChatCallModel::create(callLog, false, this);
model = ChatCallModel::create(callLog, false);
if(model)
add(model);
}
@ -999,11 +1000,11 @@ void ChatRoomModel::insertCalls (const QList<std::shared_ptr<linphone::CallLog>
if(mIsInitialized){
QList<QSharedPointer<QObject> > entries;
for(auto callLog : calls) {
QSharedPointer<ChatCallModel> model = ChatCallModel::create(callLog, true, this);
QSharedPointer<ChatCallModel> model = ChatCallModel::create(callLog, true);
if(model){
entries << model;
if (callLog->getStatus() == linphone::Call::Status::Success) {
model = ChatCallModel::create(callLog, false, this);
model = ChatCallModel::create(callLog, false);
if(model){
entries << model;
}
@ -1019,8 +1020,9 @@ void ChatRoomModel::insertCalls (const QList<std::shared_ptr<linphone::CallLog>
void ChatRoomModel::insertMessageAtEnd (const std::shared_ptr<linphone::ChatMessage> &message) {
if(mIsInitialized){
QSharedPointer<ChatMessageModel> model = ChatMessageModel::create(message, this);
QSharedPointer<ChatMessageModel> model = ChatMessageModel::create(message);
if(model){
connect(model.get(), &ChatMessageModel::remove, this, &ChatRoomModel::removeEntry);
setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount());
add(model);
}
@ -1031,9 +1033,11 @@ void ChatRoomModel::insertMessages (const QList<std::shared_ptr<linphone::ChatMe
if(mIsInitialized){
QList<QSharedPointer<QObject> > entries;
for(auto message : messages) {
QSharedPointer<ChatMessageModel> model = ChatMessageModel::create(message, this);
if(model)
QSharedPointer<ChatMessageModel> model = ChatMessageModel::create(message);
if(model){
connect(model.get(), &ChatMessageModel::remove, this, &ChatRoomModel::removeEntry);
entries << model;
}
}
if(entries.size() > 0){
prepend(entries);
@ -1045,7 +1049,7 @@ void ChatRoomModel::insertMessages (const QList<std::shared_ptr<linphone::ChatMe
void ChatRoomModel::insertNotice (const std::shared_ptr<linphone::EventLog> &eventLog) {
if(mIsInitialized){
QSharedPointer<ChatNoticeModel> model = ChatNoticeModel::create(eventLog, this);
QSharedPointer<ChatNoticeModel> model = ChatNoticeModel::create(eventLog);
if(model)
add(model);
}
@ -1055,7 +1059,7 @@ void ChatRoomModel::insertNotices (const QList<std::shared_ptr<linphone::EventLo
if(mIsInitialized){
QList<QSharedPointer<QObject> > entries;
for(auto eventLog : eventLogs) {
QSharedPointer<ChatNoticeModel> model = ChatNoticeModel::create(eventLog, this);
QSharedPointer<ChatNoticeModel> model = ChatNoticeModel::create(eventLog);
if(model) {
entries << model;
}

View file

@ -335,11 +335,14 @@ void ChatRoomProxyModel::handleIsRemoteComposingChanged () {
emit isRemoteComposingChanged();
}
void ChatRoomProxyModel::handleMessageReceived (const shared_ptr<linphone::ChatMessage> &) {
void ChatRoomProxyModel::handleMessageReceived (const shared_ptr<linphone::ChatMessage> &message) {
QWindow *window = getParentWindow(this);
if (window && window->isActive() && mChatRoomModel)
mChatRoomModel->resetMessageCount();
if (mChatRoomModel){
if(window && window->isActive())
mChatRoomModel->resetMessageCount();
//else if( message->getFromAddress()->weakEqual(CoreManager::getInstance()->getCore()->getDefaultAccount()->getParams()->getIdentityAddress()))
}
}
void ChatRoomProxyModel::handleMessageSent (const shared_ptr<linphone::ChatMessage> &) {

View file

@ -64,7 +64,7 @@ int ConferenceInfoMapModel::rowCount (const QModelIndex &) const {
QHash<int, QByteArray> ConferenceInfoMapModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "modelData";
roles[Qt::DisplayRole] = "$modelData";
roles[Qt::DisplayRole + 1] = "date";
return roles;
}

View file

@ -29,7 +29,7 @@
using namespace std;
ContactModel::ContactModel (QObject *parent, shared_ptr<linphone::Friend> linphoneFriend) : QObject(parent) {
ContactModel::ContactModel (shared_ptr<linphone::Friend> linphoneFriend, QObject * parent) : QObject(parent) {
Q_CHECK_PTR(linphoneFriend);
mLinphoneFriend = linphoneFriend;
@ -38,7 +38,7 @@ ContactModel::ContactModel (QObject *parent, shared_ptr<linphone::Friend> linpho
setVcardModelInternal(new VcardModel(linphoneFriend->getVcard()));
}
ContactModel::ContactModel (QObject *parent, VcardModel *vcardModel) : QObject(parent) {
ContactModel::ContactModel (VcardModel *vcardModel, QObject * parent) : QObject(parent) {
Q_CHECK_PTR(vcardModel);
Q_CHECK_PTR(vcardModel->mVcard);
Q_ASSERT(!vcardModel->mIsReadOnly);
@ -50,6 +50,10 @@ ContactModel::ContactModel (QObject *parent, VcardModel *vcardModel) : QObject(p
setVcardModelInternal(vcardModel);
}
ContactModel::~ContactModel(){
mVcardModel = nullptr;
mLinphoneFriend = nullptr;
}
// -----------------------------------------------------------------------------
void ContactModel::refreshPresence () {

View file

@ -24,6 +24,7 @@
#include "components/presence/Presence.hpp"
#include "utils/LinphoneEnums.hpp"
#include <QSharedPointer>
// =============================================================================
class VcardModel;
@ -35,15 +36,16 @@ class ContactModel : public QObject {
friend class SipAddressesProxyModel;
friend class SipAddressesSorter;
Q_OBJECT;
Q_OBJECT
Q_PROPERTY(Presence::PresenceStatus presenceStatus READ getPresenceStatus NOTIFY presenceStatusChanged);
Q_PROPERTY(Presence::PresenceLevel presenceLevel READ getPresenceLevel NOTIFY presenceLevelChanged);
Q_PROPERTY(VcardModel * vcard READ getVcardModel WRITE setVcardModel NOTIFY contactUpdated);
Q_PROPERTY(Presence::PresenceStatus presenceStatus READ getPresenceStatus NOTIFY presenceStatusChanged)
Q_PROPERTY(Presence::PresenceLevel presenceLevel READ getPresenceLevel NOTIFY presenceLevelChanged)
Q_PROPERTY(VcardModel * vcard READ getVcardModel WRITE setVcardModel NOTIFY contactUpdated)
public:
ContactModel (QObject *parent, std::shared_ptr<linphone::Friend> linphoneFriend);
ContactModel (QObject *parent, VcardModel *vcardModel);
ContactModel ( std::shared_ptr<linphone::Friend> linphoneFriend, QObject * parent = nullptr);
ContactModel (VcardModel *vcardModel, QObject * parent = nullptr);
virtual ~ContactModel();
void refreshPresence ();

View file

@ -92,7 +92,7 @@ static void removeBelcardPhoto (const shared_ptr<belcard::BelCard> &belcard, boo
// -----------------------------------------------------------------------------
VcardModel::VcardModel (shared_ptr<linphone::Vcard> vcard, bool isReadOnly) {
VcardModel::VcardModel (shared_ptr<linphone::Vcard> vcard, bool isReadOnly) : QObject(nullptr) {
Q_CHECK_PTR(vcard);
mVcard = vcard;
mIsReadOnly = isReadOnly;

View file

@ -34,7 +34,7 @@ namespace linphone {
class VcardModel : public QObject {
friend class ContactModel; // Grant access to `mVcard`.
Q_OBJECT;
Q_OBJECT
Q_PROPERTY(QString username READ getUsername WRITE setUsername NOTIFY vcardUpdated);
Q_PROPERTY(QString avatar READ getAvatar WRITE setAvatar NOTIFY vcardUpdated);

View file

@ -53,7 +53,7 @@ ContactsImporterListModel::ContactsImporterListModel (QObject *parent) : ProxyLi
QString pluginID = Utils::coreStringToAppString(config->getString(section, *keyName, ""));
PluginDataAPI* data = static_cast<PluginDataAPI*>(PluginsManager::createInstance(pluginID));
if(data) {
auto model = QSharedPointer<ContactsImporterModel>::create(data, this);
auto model = QSharedPointer<ContactsImporterModel>::create(data);
// See: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership
// The returned value must have a explicit parent or a QQmlEngine::CppOwnership.
engine->setObjectOwnership(model.get(), QQmlEngine::CppOwnership);
@ -103,7 +103,7 @@ ContactsImporterModel *ContactsImporterListModel::createContactsImporter(QVarian
PluginDataAPI * dataInstance = static_cast<PluginDataAPI*>(PluginsManager::createInstance(data["pluginID"].toString()));
if(dataInstance) {
// get default values
contactsImporter = QSharedPointer<ContactsImporterModel>::create(dataInstance, this);
contactsImporter = QSharedPointer<ContactsImporterModel>::create(dataInstance);
App::getInstance()->getEngine()->setObjectOwnership(contactsImporter.get(), QQmlEngine::CppOwnership);
QVariantMap newData = ContactsImporterPluginsManager::getDefaultValues(data["pluginID"].toString());// Start with defaults from plugin
QVariantMap InstanceFields = contactsImporter->getFields();

View file

@ -50,7 +50,7 @@ ContactsListModel::ContactsListModel (QObject *parent) : ProxyListModel(parent)
// Init contacts with linphone friends list.
QQmlEngine *engine = App::getInstance()->getEngine();
for (const auto &linphoneFriend : mLinphoneFriends->getFriends()) {
auto contact = QSharedPointer<ContactModel>::create(this, linphoneFriend);
auto contact = QSharedPointer<ContactModel>::create(linphoneFriend);
// See: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership
// The returned value must have a explicit parent or a QQmlEngine::CppOwnership.
@ -60,6 +60,16 @@ ContactsListModel::ContactsListModel (QObject *parent) : ProxyListModel(parent)
}
}
ContactsListModel::~ContactsListModel(){
if(rowCount()>0) {
beginResetModel();
mOptimizedSearch.clear();
mList.clear();
mLinphoneFriends = nullptr;
endResetModel();
}
}
bool ContactsListModel::removeRows (int row, int count, const QModelIndex &parent) {
int limit = row + count - 1;
@ -116,7 +126,7 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) {
return contact.get();
}
contact = QSharedPointer<ContactModel>::create(this, vcardModel);
contact = QSharedPointer<ContactModel>::create(vcardModel);
App::getInstance()->getEngine()->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership);
if (mLinphoneFriends->addFriend(contact->mLinphoneFriend) != linphone::FriendList::Status::OK) {
@ -147,8 +157,8 @@ void ContactsListModel::cleanAvatars () {
qInfo() << QStringLiteral("Delete all avatars.");
for (const auto &item : mList) {
auto contact = qobject_cast<ContactModel*>(item.get());
VcardModel *vcardModel = contact->cloneVcardModel();
auto contact = item.objectCast<ContactModel>();
VcardModel* vcardModel = contact->cloneVcardModel();
vcardModel->setAvatar(QString(""));
contact->setVcardModel(vcardModel);
}
@ -168,7 +178,7 @@ void ContactsListModel::addContact (QSharedPointer<ContactModel> contact) {
mOptimizedSearch.remove(sipAddress);
emit sipAddressRemoved(contact, sipAddress);
});
add(contact);
add<ContactModel>(contact);
for(auto address : contact->getVcardModel()->getSipAddresses()){
mOptimizedSearch[address.toString()] = contact;
}

View file

@ -41,6 +41,7 @@ class ContactsListModel : public ProxyListModel {
public:
ContactsListModel (QObject *parent = Q_NULLPTR);
virtual ~ContactsListModel();
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;

View file

@ -31,7 +31,7 @@
// =============================================================================
ContentListModel::ContentListModel (ChatMessageModel * message) : ProxyListModel(message) {
ContentListModel::ContentListModel (ChatMessageModel * message, QObject* parent) : ProxyListModel(parent) {
mParent = message;
if(message){
std::list<std::shared_ptr<linphone::Content>> contents = message->getChatMessage()->getContents() ;

View file

@ -27,7 +27,6 @@
#include <QObject>
#include <QDateTime>
#include <QString>
#include <QAbstractListModel>
#include "app/proxyModel/ProxyListModel.hpp"
@ -38,7 +37,7 @@ class ContentListModel : public ProxyListModel {
Q_OBJECT
public:
ContentListModel (ChatMessageModel * message);
ContentListModel (ChatMessageModel * message, QObject * parent = nullptr);
int count();

View file

@ -36,6 +36,10 @@ ContentProxyModel::ContentProxyModel (QObject * parent) : QSortFilterProxyModel(
setContentListModel(CoreManager::getInstance()->getChatModel()->getContentListModel().get());
}
ChatMessageModel * ContentProxyModel::getChatMessageModel() const{
return nullptr;
}
void ContentProxyModel::setChatMessageModel(ChatMessageModel * message){
if(message){
setSourceModel(message->getContents().get());

View file

@ -38,7 +38,9 @@ class ContentProxyModel : public QSortFilterProxyModel {
public:
ContentProxyModel (QObject *parent = nullptr);
Q_PROPERTY(ChatMessageModel * chatMessageModel WRITE setChatMessageModel NOTIFY chatMessageModelChanged)
Q_PROPERTY(ChatMessageModel * chatMessageModel READ getChatMessageModel WRITE setChatMessageModel NOTIFY chatMessageModelChanged)
ChatMessageModel * getChatMessageModel() const;
void setChatMessageModel(ChatMessageModel * message);
Q_INVOKABLE void setContentListModel(ContentListModel * model);

View file

@ -33,7 +33,7 @@
using namespace std;
LdapListModel::LdapListModel (QObject *parent) : QAbstractListModel(parent) {
LdapListModel::LdapListModel (QObject *parent) : ProxyListModel(parent) {
initLdap();
}
@ -42,53 +42,6 @@ void LdapListModel::reset(){
resetInternalData();
initLdap();
}
int LdapListModel::rowCount (const QModelIndex &) const {
return mServers.count();
}
QHash<int, QByteArray> LdapListModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$ldapServer";
return roles;
}
QVariant LdapListModel::data (const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mServers.count())
return QVariant();
if (role == Qt::DisplayRole)
return QVariant::fromValue(mServers[row]);
return QVariant();
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
bool LdapListModel::removeRow (int row, const QModelIndex &parent) {
return removeRows(row, 1, parent);
}
bool LdapListModel::removeRows (int row, int count, const QModelIndex &parent) {
int limit = row + count - 1;
if (row < 0 || count < 0 || limit >= mServers.count())
return false;
beginRemoveRows(parent, row, limit);
for (int i = 0; i < count; ++i)
mServers.takeAt(row)->deleteLater();
endRemoveRows();
return true;
}
// -----------------------------------------------------------------------------
@ -97,37 +50,36 @@ void LdapListModel::initLdap () {
CoreManager *coreManager = CoreManager::getInstance();
auto ldapList = coreManager->getCore()->getLdapList();
for(auto ldap : ldapList){
mServers.append(new LdapModel(ldap));
ProxyListModel::add(QSharedPointer<LdapModel>::create(ldap));
}
}
// Save if valid
void LdapListModel::enable(int id, bool status){
if( mServers[id]->isValid()){
QVariantMap config = mServers[id]->getConfig();
auto item = getAt<LdapModel>(id);
if( item->isValid()){
QVariantMap config = item->getConfig();
config["enable"] = status;
mServers[id]->setConfig(config);
mServers[id]->save();
item->setConfig(config);
item->save();
}
emit dataChanged(index(id, 0), index(id, 0));
}
// Create a new LdapModel and put it in the list
void LdapListModel::add(){
int row = mServers.count();
beginInsertRows(QModelIndex(), row, row);
auto ldap= new LdapModel(nullptr);
connect(ldap, &LdapModel::indexChanged, this, &LdapListModel::indexChanged);
auto ldap= QSharedPointer<LdapModel>::create(nullptr);
connect(ldap.get(), &LdapModel::indexChanged, this, &LdapListModel::indexChanged);
ldap->init();
mServers << ldap;
endInsertRows();
ProxyListModel::add(ldap);
emit layoutChanged();
}
void LdapListModel::remove (LdapModel *ldap) {
int index = mServers.indexOf(ldap);
if (index >=0){
ldap->unsave();
int index;
auto item = get(ldap, &index);
if(item){
item.objectCast<LdapModel>()->unsave();
removeRow(index);
}
}

View file

@ -21,15 +21,16 @@
#ifndef LDAP_LIST_MODEL_H_
#define LDAP_LIST_MODEL_H_
#include <QAbstractListModel>
#include <QDateTime>
#include "LdapModel.hpp"
#include "app/proxyModel/ProxyListModel.hpp"
// =============================================================================
class CoreHandlers;
class LdapListModel : public QAbstractListModel {
class LdapListModel : public ProxyListModel {
Q_OBJECT
public:
@ -38,11 +39,6 @@ public:
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;
// Enable the Server and save it if it is valid
Q_INVOKABLE void enable(int id, bool status);
// Create a Server
@ -54,14 +50,9 @@ signals:
void indexChanged();
private:
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
// ---------------------------------------------------------------------------
void initLdap ();
QList<LdapModel*> mServers;
};
#endif // LDAP_LIST_MODEL_H_

View file

@ -41,7 +41,7 @@ constexpr char ColorsSection[] = "ui_colors";
// =============================================================================
ColorListModel::ColorListModel ( QObject *parent) : QAbstractListModel(parent) {
ColorListModel::ColorListModel ( QObject *parent) : ProxyListModel(parent) {
initKeywords();
init();
}
@ -68,15 +68,11 @@ void ColorListModel::initKeywords(){
mKeywordsMap["fg"] = "foreground";
}
int ColorListModel::rowCount (const QModelIndex &index) const{
return mList.count();
}
QHash<int, QByteArray> ColorListModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$color";
roles[Qt::UserRole] = "id";
roles[Qt::UserRole+1] = "modelData";
roles[Qt::UserRole+1] = "$modelData";
return roles;
}
@ -87,30 +83,16 @@ QVariant ColorListModel::data (const QModelIndex &index, int role) const {
return QVariant();
if (role >= Qt::UserRole)
return mList[row]->getName();
return mList[row].objectCast<ColorModel>()->getName();
return QVariant::fromValue(mList[row].get());
//return QVariant();
}
ColorModel *ColorListModel::getAt(const int& index){
return mList[index].get();
}
void ColorListModel::add(std::shared_ptr<ColorModel> color){
int row = mList.count();
void ColorListModel::add(QSharedPointer<ColorModel> color){
connect(color.get(), &ColorModel::uiColorChanged, this, &ColorListModel::handleUiColorChanged);
beginInsertRows(QModelIndex(), row, row);
setProperty(color->getName().toStdString().c_str(), QVariant::fromValue(color.get()));
mData.insert(color->getName(), QVariant::fromValue(color.get()));
mList << color;
endInsertRows();
ProxyListModel::add(color);
emit layoutChanged();
}
@ -138,7 +120,7 @@ ColorModel * ColorListModel::add(const QString& id, const QString& idLink, QStri
}
addLink(id, idLink);
}
auto colorShared = std::make_shared<ColorModel>(id, colorValue, description);
auto colorShared = QSharedPointer<ColorModel>::create(id, colorValue, description);
add(colorShared);
color = colorShared.get();
emit colorChanged();
@ -184,23 +166,6 @@ void ColorListModel::updateLink(const QString& id, const QString& newLink){
}
}
bool ColorListModel::removeRow (int row, const QModelIndex &parent){
return removeRows(row, 1, parent);
}
bool ColorListModel::removeRows (int row, int count, const QModelIndex &parent) {
int limit = row + count - 1;
if (row < 0 || count < 0 || limit >= mList.count())
return false;
beginRemoveRows(parent, row, limit);
for (int i = 0; i < count; ++i)
mList.takeAt(row);
endRemoveRows();
return true;
}
void ColorListModel::useConfig (const std::shared_ptr<linphone::Config> &config) {
#if LINPHONE_FRIDAY
if (!isLinphoneFriday())
@ -273,7 +238,8 @@ void ColorListModel::overrideColors (const std::shared_ptr<linphone::Config> &co
bool haveColor = false;
QString qtConfigId = QString::fromStdString(configId);
QString colorName = QString::fromStdString(colorsConfig->getString(ColorsSection, configId, ""));
for(auto color : mList){
for(auto item : mList){
auto color = item.objectCast<ColorModel>();
QString name = color->getName();
if( name == qtConfigId) {
color->setColor(QColor(colorName));
@ -284,16 +250,7 @@ void ColorListModel::overrideColors (const std::shared_ptr<linphone::Config> &co
add(qtConfigId, "", "Added from Configuration", colorName);
}
}
}
/*
for(auto color : mList){
QString name = color->getName();
const std::string colorValue = config->getString(ColorsSection, name.toStdString(), "");
if(!colorValue.empty()){
color->setColor(QColor(QString::fromStdString(colorValue)));
}
}*/
}
}
std::shared_ptr<linphone::Config> ColorListModel::getConfigColors(const QString filename){
@ -304,7 +261,8 @@ std::shared_ptr<linphone::Config> ColorListModel::getConfigColors(const QString
links.push_back((link.key()+";"+QString::number(link.value())).toStdString());
}
config->setStringList(ColorsSection, "ColorLinks", links);
for(auto color : mList){
for(auto item : mList){
auto color = item.objectCast<ColorModel>();
config->setString(ColorsSection, color->getName().toStdString(), color->getColor().name(QColor::HexArgb).toStdString());
}
return config;

View file

@ -25,14 +25,15 @@
#include <QObject>
#include <QDateTime>
#include <QString>
#include <QAbstractListModel>
#include <memory>
#include <QQmlPropertyMap>
#include <QSharedPointer>
#include "ColorModel.hpp"
#include "app/proxyModel/ProxyListModel.hpp"
#define ADD_COLOR(COLOR, VALUE, DESCRIPTION) \
color = std::make_shared<ColorModel>(COLOR, VALUE, DESCRIPTION); \
color = QSharedPointer<ColorModel>::create(COLOR, VALUE, DESCRIPTION); \
add(color);
#define ADD_COLOR_WITH_LINK(COLOR, VALUE, DESCRIPTION, LINK) \
@ -40,17 +41,17 @@
// Alpha is in percent.
#define ADD_COLOR_WITH_ALPHA(COLOR, ALPHA, DESCRIPTION) \
color = std::make_shared<ColorModel>(COLOR + QString::number(ALPHA), mData[COLOR].value<ColorModel*>()->getColor().name(), DESCRIPTION); \
color = QSharedPointer<ColorModel>::create(COLOR + QString::number(ALPHA), mData[COLOR].value<ColorModel*>()->getColor().name(), DESCRIPTION); \
color->setAlpha(ALPHA * 255 / 100); \
add(color);
class ColorModel;
class ColorListModel : public QAbstractListModel {
class ColorListModel : public ProxyListModel {
Q_OBJECT
void init() {
std::shared_ptr<ColorModel> color;
QSharedPointer<ColorModel> color;
ADD_COLOR("a", "transparent", "Generic transparent color.")
// Primary color for hovered items.
ADD_COLOR("b", "#D64D00", "Primary color for hovered items.")
@ -304,11 +305,8 @@ public:
ColorListModel (QObject *parent = nullptr);
void initKeywords();
int rowCount (const QModelIndex &index = QModelIndex()) const override;
virtual QHash<int, QByteArray> roleNames () const override;
virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
ColorModel *getAt(const int& index);
void useConfig (const std::shared_ptr<linphone::Config> &config);
@ -342,13 +340,9 @@ signals:
void colorChanged();
private:
void add(std::shared_ptr<ColorModel> imdn);
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
virtual bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
void add(QSharedPointer<ColorModel> imdn);
QString buildDescription(QString description); // return a description from id by splitting '_'
QList<std::shared_ptr<ColorModel>> mList;
QStringList getColorNames () const;
QQmlPropertyMap mData;
@ -359,6 +353,6 @@ private:
};
#undef ADD_COLOR
Q_DECLARE_METATYPE(std::shared_ptr<ColorListModel>)
Q_DECLARE_METATYPE(QSharedPointer<ColorListModel>)
#endif

View file

@ -63,6 +63,6 @@ private:
QString mLinkedToImage;
};
Q_DECLARE_METATYPE(std::shared_ptr<ColorModel>);
Q_DECLARE_METATYPE(QSharedPointer<ColorModel>);
#endif

View file

@ -43,7 +43,7 @@ namespace {
// =============================================================================
ImageListModel::ImageListModel ( QObject *parent) : QAbstractListModel(parent), mData(this) {
ImageListModel::ImageListModel ( QObject *parent) : ProxyListModel(parent), mData(this) {
// Get all internals
QString path = ":/assets/images/";
QStringList filters;
@ -51,59 +51,21 @@ ImageListModel::ImageListModel ( QObject *parent) : QAbstractListModel(parent),
QFileInfoList files = QDir(path).entryInfoList(filters, QDir::Files , QDir::Name);
for(QFileInfo file : files){
std::shared_ptr<ImageModel> model = std::make_shared<ImageModel>(file.completeBaseName(), path+file.fileName(), "");
QSharedPointer<ImageModel> model = QSharedPointer<ImageModel>::create(file.completeBaseName(), path+file.fileName(), "");
add(model);
}
mData.insert("areReadOnlyImages", QVariant::fromValue(true));
}
int ImageListModel::rowCount (const QModelIndex &index) const{
return mList.count();
}
QHash<int, QByteArray> ImageListModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$image";
return roles;
}
QVariant ImageListModel::data (const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mList.count())
return QVariant();
return QVariant::fromValue(mList[row].get());
}
void ImageListModel::add(std::shared_ptr<ImageModel> image){
int row = mList.count();
beginInsertRows(QModelIndex(), row, row);
void ImageListModel::add(QSharedPointer<ImageModel> image){
setProperty(image->getId().toStdString().c_str(), QVariant::fromValue(image.get()));
mData.insert(image->getId(), QVariant::fromValue(image.get()));
mList << image;
endInsertRows();
ProxyListModel::add(image);
emit layoutChanged();
}
bool ImageListModel::removeRow (int row, const QModelIndex &parent){
return removeRows(row, 1, parent);
}
bool ImageListModel::removeRows (int row, int count, const QModelIndex &parent) {
int limit = row + count - 1;
if (row < 0 || count < 0 || limit >= mList.count())
return false;
beginRemoveRows(parent, row, limit);
for (int i = 0; i < count; ++i)
mList.takeAt(row);
endRemoveRows();
return true;
}
void ImageListModel::useConfig (const std::shared_ptr<linphone::Config> &config) {
#if LINPHONE_FRIDAY
if (!isLinphoneFriday())
@ -134,9 +96,11 @@ const QQmlPropertyMap * ImageListModel::getQmlData() const{
}
ImageModel * ImageListModel::getImageModel(const QString& id){
for(auto image : mList)
for(auto item : mList) {
auto image = item.objectCast<ImageModel>();
if(image->getId() == id)
return image.get();
}
return nullptr;
}
@ -144,7 +108,8 @@ ImageModel * ImageListModel::getImageModel(const QString& id){
void ImageListModel::overrideImages (const std::shared_ptr<linphone::Config> &config) {
if (!config)
return;
for(auto image : mList){
for(auto item : mList){
auto image = item.objectCast<ImageModel>();
QString id = image->getId();
const std::string pathValue = config->getString(ImagesSection, id.toStdString(), "");
if(!pathValue.empty()){

View file

@ -25,25 +25,20 @@
#include <QObject>
#include <QDateTime>
#include <QString>
#include <QAbstractListModel>
#include <memory>
#include <QQmlPropertyMap>
#include <QSharedPointer>
#include "ImageModel.hpp"
#include "app/proxyModel/ProxyListModel.hpp"
class ImageModel;
class ImageListModel : public QAbstractListModel {
class ImageListModel : public ProxyListModel {
Q_OBJECT
public:
ImageListModel (QObject *parent = nullptr);
int rowCount (const QModelIndex &index = QModelIndex()) const override;
virtual QHash<int, QByteArray> roleNames () const override;
virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
void useConfig (const std::shared_ptr<linphone::Config> &config);
Q_INVOKABLE QString getIds();
@ -54,11 +49,7 @@ public:
ImageModel * getImageModel(const QString& id);
private:
void add(std::shared_ptr<ImageModel> imdn);
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
virtual bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
QList<std::shared_ptr<ImageModel>> mList;
void add(QSharedPointer<ImageModel> imdn);
void overrideImages (const std::shared_ptr<linphone::Config> &config);
@ -68,6 +59,6 @@ private:
bool mAreReadOnlyImages = true;
};
Q_DECLARE_METATYPE(std::shared_ptr<ImageListModel>)
Q_DECLARE_METATYPE(QSharedPointer<ImageListModel>)
#endif

View file

@ -31,7 +31,7 @@
// =============================================================================
ParticipantImdnStateListModel::ParticipantImdnStateListModel (std::shared_ptr<linphone::ChatMessage> message, QObject *parent) : QAbstractListModel(parent) {
ParticipantImdnStateListModel::ParticipantImdnStateListModel (std::shared_ptr<linphone::ChatMessage> message, QObject *parent) : ProxyListModel(parent) {
QVector<linphone::ChatMessage::State> states;
states.push_back(linphone::ChatMessage::State::Delivered);
states.push_back(linphone::ChatMessage::State::DeliveredToUser);
@ -41,78 +41,28 @@ ParticipantImdnStateListModel::ParticipantImdnStateListModel (std::shared_ptr<li
std::list<std::shared_ptr<linphone::ParticipantImdnState>> imdns = message->getParticipantsByImdnState(states[i]);
for(auto imdn : imdns){
if(imdn->getParticipant()){
auto deviceModel = std::make_shared<ParticipantImdnStateModel>(imdn);
auto deviceModel = QSharedPointer<ParticipantImdnStateModel>::create(imdn);
mList << deviceModel;
}
}
}
}
int ParticipantImdnStateListModel::rowCount (const QModelIndex &index) const{
return mList.count();
}
QHash<int, QByteArray> ParticipantImdnStateListModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$participantImdn";
return roles;
}
QVariant ParticipantImdnStateListModel::data (const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mList.count())
return QVariant();
if (role == Qt::DisplayRole)
return QVariant::fromValue(mList[row].get());
return QVariant();
}
void ParticipantImdnStateListModel::add(std::shared_ptr<ParticipantImdnStateModel> imdn){
int row = mList.count();
beginInsertRows(QModelIndex(), row, row);
mList << imdn;
endInsertRows();
emit countChanged();
emit layoutChanged();
}
bool ParticipantImdnStateListModel::removeRow (int row, const QModelIndex &parent){
return removeRows(row, 1, parent);
}
bool ParticipantImdnStateListModel::removeRows (int row, int count, const QModelIndex &parent) {
int limit = row + count - 1;
if (row < 0 || count < 0 || limit >= mList.count())
return false;
beginRemoveRows(parent, row, limit);
for (int i = 0; i < count; ++i)
mList.takeAt(row);
endRemoveRows();
emit countChanged();
return true;
}
//--------------------------------------------------------------------------------
std::shared_ptr<ParticipantImdnStateModel> ParticipantImdnStateListModel::getImdnState(const std::shared_ptr<const linphone::ParticipantImdnState> & state){
std::shared_ptr<ParticipantImdnStateModel> imdn;
QSharedPointer<ParticipantImdnStateModel> ParticipantImdnStateListModel::getImdnState(const std::shared_ptr<const linphone::ParticipantImdnState> & state){
QSharedPointer<ParticipantImdnStateModel> imdn;
auto participant = state->getParticipant();
auto it = mList.begin();
if( participant){
auto imdnAddress = state->getParticipant()->getAddress();
while(it != mList.end() && !(*it)->getAddress()->equal(imdnAddress))
while(it != mList.end() && !it->objectCast<ParticipantImdnStateModel>()->getAddress()->equal(imdnAddress))
++it;
}else
it = mList.end();
if(it != mList.end())
imdn = *it;
imdn = it->objectCast<ParticipantImdnStateModel>();
else{// Create the new one
imdn = std::make_shared<ParticipantImdnStateModel>(state);
imdn = QSharedPointer<ParticipantImdnStateModel>::create(state);
add(imdn);
}
return imdn;

View file

@ -27,22 +27,18 @@
#include <QObject>
#include <QDateTime>
#include <QString>
#include <QAbstractListModel>
#include "app/proxyModel/ProxyListModel.hpp"
class ParticipantImdnStateModel;
class ParticipantImdnStateListModel : public QAbstractListModel {
class ParticipantImdnStateListModel : public ProxyListModel {
Q_OBJECT
public:
ParticipantImdnStateListModel (std::shared_ptr<linphone::ChatMessage> message, QObject *parent = nullptr);
int rowCount (const QModelIndex &index = QModelIndex()) const override;
virtual QHash<int, QByteArray> roleNames () const override;
virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
std::shared_ptr<ParticipantImdnStateModel> getImdnState(const std::shared_ptr<const linphone::ParticipantImdnState> & state);
QSharedPointer<ParticipantImdnStateModel> getImdnState(const std::shared_ptr<const linphone::ParticipantImdnState> & state);
void updateState(const std::shared_ptr<const linphone::ParticipantImdnState> & state);
@ -51,17 +47,8 @@ public slots:
signals:
void imdnStateChanged();
void countChanged();
private:
void add(std::shared_ptr<ParticipantImdnStateModel> imdn);
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
virtual bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
QList<std::shared_ptr<ParticipantImdnStateModel>> mList;
};
Q_DECLARE_METATYPE(std::shared_ptr<ParticipantImdnStateListModel>)
Q_DECLARE_METATYPE(QSharedPointer<ParticipantImdnStateListModel>)
#endif

View file

@ -51,7 +51,7 @@ bool ParticipantImdnStateProxyModel::lessThan (const QModelIndex &left, const QM
}
//---------------------------------------------------------------------------------
int ParticipantImdnStateProxyModel::getCount(){
return rowCount();
return sourceModel() ? sourceModel()->rowCount() : 0;
}
ChatMessageModel * ParticipantImdnStateProxyModel::getChatMessageModel(){

View file

@ -30,7 +30,7 @@
// =============================================================================
ParticipantDeviceListModel::ParticipantDeviceListModel (std::shared_ptr<linphone::Participant> participant, QObject *parent) : QAbstractListModel(parent) {
ParticipantDeviceListModel::ParticipantDeviceListModel (std::shared_ptr<linphone::Participant> participant, QObject *parent) : ProxyListModel(parent) {
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices = participant->getDevices() ;
auto previewModel = ParticipantDeviceModel::create(nullptr, true);
mList << previewModel;
@ -41,7 +41,7 @@ ParticipantDeviceListModel::ParticipantDeviceListModel (std::shared_ptr<linphone
}
}
ParticipantDeviceListModel::ParticipantDeviceListModel (CallModel * callModel, QObject *parent) : QAbstractListModel(parent) {
ParticipantDeviceListModel::ParticipantDeviceListModel (CallModel * callModel, QObject *parent) : ProxyListModel(parent) {
if(callModel && callModel->isConference()) {
mCallModel = callModel;
auto conferenceModel = callModel->getConferenceModel();
@ -69,16 +69,6 @@ ParticipantDeviceListModel::ParticipantDeviceListModel (CallModel * callModel, Q
}
}
int ParticipantDeviceListModel::rowCount (const QModelIndex &index) const{
qWarning() << "rowCount: " << mList.count();
return mList.count();
}
int ParticipantDeviceListModel::count(){
qWarning() << "count: " << mList.count();
return mList.count();
}
void ParticipantDeviceListModel::updateDevices(std::shared_ptr<linphone::Participant> participant){
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices = participant->getDevices() ;
auto previewModel = ParticipantDeviceModel::create(nullptr, true);
@ -127,44 +117,6 @@ void ParticipantDeviceListModel::updateDevices(const std::list<std::shared_ptr<l
*/
}
QHash<int, QByteArray> ParticipantDeviceListModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$participantDevice";
return roles;
}
QVariant ParticipantDeviceListModel::data (const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mList.count())
return QVariant();
if (role == Qt::DisplayRole)
return QVariant::fromValue(mList[row].get());
return QVariant();
}
bool ParticipantDeviceListModel::removeRow (int row, const QModelIndex &parent){
return removeRows(row, 1, parent);
}
bool ParticipantDeviceListModel::removeRows (int row, int count, const QModelIndex &parent) {
int limit = row + count - 1;
if (row < 0 || count < 0 || limit >= mList.count())
return false;
beginRemoveRows(parent, row, limit);
for (int i = 0; i < count; ++i)
mList.takeAt(row);
endRemoveRows();
return true;
}
void ParticipantDeviceListModel::onSecurityLevelChanged(std::shared_ptr<const linphone::Address> device){
emit securityLevelChanged(device);
}
@ -177,14 +129,9 @@ void ParticipantDeviceListModel::onParticipantDeviceAdded(const std::shared_ptr<
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices = conferenceModel->getConference()->getParticipantDeviceList();
for(auto realParticipantDevice : devices){
if( realParticipantDevice == participantDevice){
int row = mList.count();
auto deviceModel = ParticipantDeviceModel::create(realParticipantDevice, false);
connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged);
beginInsertRows(QModelIndex(), row, row);
mList << deviceModel;
endInsertRows();
emit countChanged();
//emit layoutChanged();
add(deviceModel);
return;
}
}
@ -195,10 +142,8 @@ void ParticipantDeviceListModel::onParticipantDeviceRemoved(const std::shared_pt
qWarning() << "Removing participant";
int row = 0;
for(auto device : mList){
if( device->getDevice() == participantDevice){
if( device.objectCast<ParticipantDeviceModel>()->getDevice() == participantDevice){
removeRow(row);
emit countChanged();
//emit layoutChanged();
return;
}
++row;

View file

@ -27,30 +27,23 @@
#include <QObject>
#include <QDateTime>
#include <QString>
#include <QAbstractListModel>
#include "app/proxyModel/ProxyListModel.hpp"
class CallModel;
class ParticipantDeviceModel;
class ParticipantDeviceListModel : public QAbstractListModel {
class ParticipantDeviceListModel : public ProxyListModel {
Q_OBJECT
public:
ParticipantDeviceListModel (std::shared_ptr<linphone::Participant> participant, QObject *parent = nullptr);
ParticipantDeviceListModel (CallModel * callModel, QObject *parent = nullptr);
int rowCount (const QModelIndex &index = QModelIndex()) const override;
int count();
void updateDevices(std::shared_ptr<linphone::Participant> participant);
void updateDevices(const std::list<std::shared_ptr<linphone::ParticipantDevice>>& devices, const bool& isMe);
virtual QHash<int, QByteArray> roleNames () const override;
virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
public slots:
void onSecurityLevelChanged(std::shared_ptr<const linphone::Address> device);
void onParticipantDeviceAdded(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void onParticipantDeviceRemoved(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void onParticipantDeviceJoined(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
@ -59,13 +52,8 @@ public slots:
signals:
void securityLevelChanged(std::shared_ptr<const linphone::Address> device);
void countChanged();
private:
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
virtual bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
QList<std::shared_ptr<ParticipantDeviceModel>> mList;
CallModel * mCallModel = nullptr;
};

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2022 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 "ParticipantDeviceListener.hpp"
// =============================================================================
ParticipantDeviceListener::ParticipantDeviceListener(QObject *parent) : QObject(parent) {
}
//--------------------------------------------------------------------
void ParticipantDeviceListener::onIsSpeakingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isSpeaking) {
emit isSpeakingChanged(participantDevice, isSpeaking);
}
void ParticipantDeviceListener::onIsMuted(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isMutedVar) {
emit isMuted(participantDevice, isMutedVar);
}
void ParticipantDeviceListener::onConferenceJoined(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice) {
emit conferenceJoined(participantDevice);
}
void ParticipantDeviceListener::onConferenceLeft(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice) {
emit conferenceLeft(participantDevice);
}
void ParticipantDeviceListener::onStreamCapabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::MediaDirection direction, linphone::StreamType streamType) {
emit streamCapabilityChanged(participantDevice, direction, streamType);
}
void ParticipantDeviceListener::onStreamAvailabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool available, linphone::StreamType streamType) {
emit streamAvailabilityChanged(participantDevice, available, streamType);
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2022 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 PARTICIPANT_DEVICE_LISTENER_H_
#define PARTICIPANT_DEVICE_LISTENER_H_
#include <linphone++/linphone.hh>
// =============================================================================
#include <QObject>
#include <QDateTime>
#include <QString>
class CallModel;
class ParticipantDeviceListener : public QObject, public linphone::ParticipantDeviceListener {
Q_OBJECT
public:
ParticipantDeviceListener (QObject *parent = nullptr);
//void deviceSecurityLevelChanged(std::shared_ptr<const linphone::Address> device);
virtual void onIsSpeakingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isSpeaking) override;
virtual void onIsMuted(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isMuted) override;
virtual void onConferenceJoined(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice) override;
virtual void onConferenceLeft(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice) override;
virtual void onStreamCapabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::MediaDirection direction, linphone::StreamType streamType) override;
virtual void onStreamAvailabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool available, linphone::StreamType streamType) override;
signals:
void isSpeakingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isSpeaking);
void isMuted(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isMuted);
void conferenceJoined(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice);
void conferenceLeft(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice);
void streamCapabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::MediaDirection direction, linphone::StreamType streamType);
void streamAvailabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool available, linphone::StreamType streamType);
};
#endif // PARTICIPANT_MODEL_H_

View file

@ -19,18 +19,31 @@
*/
#include "ParticipantDeviceModel.hpp"
#include "ParticipantDeviceListener.hpp"
#include <QQmlApplicationEngine>
#include "app/App.hpp"
#include "utils/Utils.hpp"
#include "components/Components.hpp"
void ParticipantDeviceModel::connectTo(ParticipantDeviceListener * listener){
connect(listener, &ParticipantDeviceListener::isSpeakingChanged, this, &ParticipantDeviceModel::onIsSpeakingChanged);
connect(listener, &ParticipantDeviceListener::isMuted, this, &ParticipantDeviceModel::onIsMuted);
connect(listener, &ParticipantDeviceListener::conferenceJoined, this, &ParticipantDeviceModel::onConferenceJoined);
connect(listener, &ParticipantDeviceListener::conferenceLeft, this, &ParticipantDeviceModel::onConferenceLeft);
connect(listener, &ParticipantDeviceListener::streamCapabilityChanged, this, &ParticipantDeviceModel::onStreamCapabilityChanged);
connect(listener, &ParticipantDeviceListener::streamAvailabilityChanged, this, &ParticipantDeviceModel::onStreamAvailabilityChanged);
}
// =============================================================================
ParticipantDeviceModel::ParticipantDeviceModel (std::shared_ptr<linphone::ParticipantDevice> device, const bool& isMe, QObject *parent) : QObject(parent) {
App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE
mIsMe = isMe;
mParticipantDevice = device;
mParticipantDeviceListener = std::make_shared<ParticipantDeviceListener>(nullptr);
if( device)
device->addListener(mParticipantDeviceListener);
mCall = nullptr;
}
/*
@ -42,12 +55,15 @@ ParticipantDeviceModel::ParticipantDeviceModel (CallModel * call, const bool& is
connect(call, &CallModel::statusChanged, this, &ParticipantDeviceModel::videoEnabledChanged);
}*/
std::shared_ptr<ParticipantDeviceModel> ParticipantDeviceModel::create(std::shared_ptr<linphone::ParticipantDevice> device, const bool& isMe, QObject *parent){
std::shared_ptr<ParticipantDeviceModel> model = std::make_shared<ParticipantDeviceModel>(device, isMe, parent);
ParticipantDeviceModel::~ParticipantDeviceModel(){
if( mParticipantDevice)
mParticipantDevice->removeListener(mParticipantDeviceListener);
}
QSharedPointer<ParticipantDeviceModel> ParticipantDeviceModel::create(std::shared_ptr<linphone::ParticipantDevice> device, const bool& isMe, QObject *parent){
QSharedPointer<ParticipantDeviceModel> model = QSharedPointer<ParticipantDeviceModel>::create(device, isMe, parent);
if(model){
model->mSelf = model;
if(device)
device->addListener(model);
return model;
}
return nullptr;

View file

@ -27,18 +27,21 @@
#include <QObject>
#include <QDateTime>
#include <QString>
#include <QSharedPointer>
class CallModel;
class ParticipantDeviceListener;
class ParticipantDeviceModel : public QObject, public linphone::ParticipantDeviceListener {
class ParticipantDeviceModel : public QObject {
Q_OBJECT
public:
ParticipantDeviceModel (std::shared_ptr<linphone::ParticipantDevice> device, const bool& isMe = false, QObject *parent = nullptr);
virtual ~ParticipantDeviceModel();
//ParticipantDeviceModel (CallModel * call, const bool& isMe = true, QObject *parent = nullptr);
static std::shared_ptr<ParticipantDeviceModel> create(std::shared_ptr<linphone::ParticipantDevice> device, const bool& isMe = false, QObject *parent = nullptr);
static QSharedPointer<ParticipantDeviceModel> create(std::shared_ptr<linphone::ParticipantDevice> device, const bool& isMe = false, QObject *parent = nullptr);
//static std::shared_ptr<ParticipantDeviceModel> create(CallModel * call, const bool& isMe = true, QObject *parent = nullptr);
Q_PROPERTY(QString name READ getName CONSTANT)
@ -58,15 +61,14 @@ public:
std::shared_ptr<linphone::ParticipantDevice> getDevice();
//void deviceSecurityLevelChanged(std::shared_ptr<const linphone::Address> device);
virtual void onIsSpeakingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isSpeaking) override;
virtual void onIsMuted(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isMuted) override;
virtual void onConferenceJoined(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice) override;
virtual void onConferenceLeft(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice) override;
virtual void onStreamCapabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::MediaDirection direction, linphone::StreamType streamType) override;
virtual void onStreamAvailabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool available, linphone::StreamType streamType) override;
virtual void onIsSpeakingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isSpeaking);
virtual void onIsMuted(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isMuted);
virtual void onConferenceJoined(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice);
virtual void onConferenceLeft(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice);
virtual void onStreamCapabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::MediaDirection direction, linphone::StreamType streamType);
virtual void onStreamAvailabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool available, linphone::StreamType streamType);
void connectTo(ParticipantDeviceListener * listener);
public slots:
void onSecurityLevelChanged(std::shared_ptr<const linphone::Address> device);
signals:
@ -78,11 +80,11 @@ private:
bool mIsMe = false;
std::shared_ptr<linphone::ParticipantDevice> mParticipantDevice;
std::shared_ptr<ParticipantDeviceListener> mParticipantDeviceListener; // This is passed to linpĥone object and must be in shared_ptr
CallModel * mCall;
std::weak_ptr<ParticipantDeviceModel> mSelf;
QWeakPointer<ParticipantDeviceModel> mSelf;
};
//Q_DECLARE_METATYPE(ParticipantModel *);
Q_DECLARE_METATYPE(std::shared_ptr<ParticipantDeviceModel>)
Q_DECLARE_METATYPE(QSharedPointer<ParticipantDeviceModel>)
#endif // PARTICIPANT_MODEL_H_

View file

@ -31,7 +31,7 @@
// =============================================================================
ParticipantListModel::ParticipantListModel (ChatRoomModel * chatRoomModel, QObject *parent) : QAbstractListModel(parent) {
ParticipantListModel::ParticipantListModel (ChatRoomModel * chatRoomModel, QObject *parent) : ProxyListModel(parent) {
if( chatRoomModel) {
mChatRoomModel = chatRoomModel;//CoreManager::getInstance()->getChatRoomModel(chatRoomModel);
@ -52,35 +52,28 @@ ParticipantListModel::ParticipantListModel (ChatRoomModel * chatRoomModel, QObje
}
}
ParticipantListModel::~ParticipantListModel(){
mParticipants.clear();
mList.clear();
mChatRoomModel = nullptr;
}
// -----------------------------------------------------------------------------
ParticipantModel * ParticipantListModel::getAt(const int& index){
return mParticipants[index].get();
}
ChatRoomModel *ParticipantListModel::getChatRoomModel() const{
return mChatRoomModel;
}
int ParticipantListModel::getCount() const{
return mParticipants.size();
}
std::list<std::shared_ptr<linphone::Address>> ParticipantListModel::getParticipants()const{
std::list<std::shared_ptr<linphone::Address>> participants;
for(auto participant : mParticipants){
participants.push_back(Utils::interpretUrl(participant->getSipAddress()));
for(auto participant : mList){
participants.push_back(Utils::interpretUrl(participant.objectCast<ParticipantModel>()->getSipAddress()));
}
return participants;
}
QString ParticipantListModel::addressesToString()const{
QStringList txt;
for(auto participant : mParticipants){
for(auto item : mList){
auto participant = item.objectCast<ParticipantModel>();
if( participant->getParticipant())// is Participant. We test it because this participant is not accepted by chat room yet.
txt << Utils::coreStringToAppString(participant->getParticipant()->getAddress()->asStringUriOnly());
}
@ -90,8 +83,8 @@ QString ParticipantListModel::addressesToString()const{
QString ParticipantListModel::displayNamesToString()const{
QStringList txt;
for(auto participant : mParticipants){
auto p = participant->getParticipant();
for(auto participant : mList){
auto p = participant.objectCast<ParticipantModel>()->getParticipant();
if(p){
QString displayName = Utils::getDisplayName(p->getAddress());
if(displayName != "")
@ -104,10 +97,11 @@ QString ParticipantListModel::displayNamesToString()const{
QString ParticipantListModel::usernamesToString()const{
QStringList txt;
for(auto participant : mParticipants){
std::string username = participant->getParticipant()->getAddress()->getDisplayName();
for(auto item : mList){
auto participant = item.objectCast<ParticipantModel>()->getParticipant();
std::string username = participant->getAddress()->getDisplayName();
if(username == "")
username = participant->getParticipant()->getAddress()->getUsername();
username = participant->getAddress()->getUsername();
txt << Utils::coreStringToAppString(username);
}
txt.removeFirst();// Remove me
@ -117,62 +111,11 @@ QString ParticipantListModel::usernamesToString()const{
bool ParticipantListModel::contains(const QString& address) const{
auto testAddress = Utils::interpretUrl(address);
bool exists = false;
for(auto itParticipant = mParticipants.begin() ; !exists && itParticipant != mParticipants.end() ; ++itParticipant)
exists = testAddress->weakEqual(Utils::interpretUrl((*itParticipant)->getSipAddress() ));
for(auto itParticipant = mList.begin() ; !exists && itParticipant != mList.end() ; ++itParticipant)
exists = testAddress->weakEqual(Utils::interpretUrl(itParticipant->objectCast<ParticipantModel>()->getSipAddress() ));
return exists;
}
//----------------------------------------------------------------------------
int ParticipantListModel::rowCount (const QModelIndex &) const {
return mParticipants.count();
}
QHash<int, QByteArray> ParticipantListModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$participant";
return roles;
}
QVariant ParticipantListModel::data (const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mParticipants.count())
return QVariant();
if (role == Qt::DisplayRole)
return QVariant::fromValue(mParticipants[row].get());
return QVariant();
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
bool ParticipantListModel::removeRow (int row, const QModelIndex &parent) {
return removeRows(row, 1, parent);
}
bool ParticipantListModel::removeRows (int row, int count, const QModelIndex &parent) {
int limit = row + count - 1;
if (row < 0 || count < 0 || limit >= mParticipants.count())
return false;
beginRemoveRows(parent, row, limit);
for (int i = 0; i < count; ++i){
mParticipants.takeAt(row);
}
endRemoveRows();
emit countChanged();
return true;
}
// -----------------------------------------------------------------------------
void ParticipantListModel::updateParticipants () {
@ -183,21 +126,21 @@ void ParticipantListModel::updateParticipants () {
dbParticipants.push_front(me);
//Remove left participants
//for(auto participant : mParticipants){
auto itParticipant = mParticipants.begin();
while(itParticipant != mParticipants.end()) {
//for(auto participant : mList){
auto itParticipant = mList.begin();
while(itParticipant != mList.end()) {
auto itDbParticipant = dbParticipants.begin();
while(itDbParticipant != dbParticipants.end()
&& ((*itParticipant)->getParticipant() && !(*itDbParticipant)->getAddress()->weakEqual((*itParticipant)->getParticipant()->getAddress())
|| !(*itParticipant)->getParticipant() && !(*itDbParticipant)->getAddress()->weakEqual(Utils::interpretUrl((*itParticipant)->getSipAddress()))
&& (itParticipant->objectCast<ParticipantModel>()->getParticipant() && !(*itDbParticipant)->getAddress()->weakEqual(itParticipant->objectCast<ParticipantModel>()->getParticipant()->getAddress())
|| !itParticipant->objectCast<ParticipantModel>()->getParticipant() && !(*itDbParticipant)->getAddress()->weakEqual(Utils::interpretUrl(itParticipant->objectCast<ParticipantModel>()->getSipAddress()))
)
){
++itDbParticipant;
}
if( itDbParticipant == dbParticipants.end()){
int row = itParticipant - mParticipants.begin();
int row = itParticipant - mList.begin();
beginRemoveRows(QModelIndex(), row, row);
itParticipant = mParticipants.erase(itParticipant);
itParticipant = mList.erase(itParticipant);
endRemoveRows();
changed = true;
}else
@ -205,26 +148,23 @@ void ParticipantListModel::updateParticipants () {
}
// Add new
for(auto dbParticipant : dbParticipants){
auto itParticipant = mParticipants.begin();
while(itParticipant != mParticipants.end() && ( (*itParticipant)->getParticipant() && !dbParticipant->getAddress()->weakEqual((*itParticipant)->getParticipant()->getAddress())
|| (!(*itParticipant)->getParticipant() && !dbParticipant->getAddress()->weakEqual(Utils::interpretUrl((*itParticipant)->getSipAddress())))
auto itParticipant = mList.begin();
while(itParticipant != mList.end() && ( itParticipant->objectCast<ParticipantModel>()->getParticipant() && !dbParticipant->getAddress()->weakEqual(itParticipant->objectCast<ParticipantModel>()->getParticipant()->getAddress())
|| (!itParticipant->objectCast<ParticipantModel>()->getParticipant() && !dbParticipant->getAddress()->weakEqual(Utils::interpretUrl(itParticipant->objectCast<ParticipantModel>()->getSipAddress())))
)
){
++itParticipant;
}
if( itParticipant == mParticipants.end()){
auto participant = std::make_shared<ParticipantModel>(dbParticipant);
if( itParticipant == mList.end()){
auto participant = QSharedPointer<ParticipantModel>::create(dbParticipant);
connect(this, &ParticipantListModel::deviceSecurityLevelChanged, participant.get(), &ParticipantModel::onDeviceSecurityLevelChanged);
connect(this, &ParticipantListModel::securityLevelChanged, participant.get(), &ParticipantModel::onSecurityLevelChanged);
connect(participant.get(),&ParticipantModel::updateAdminStatus, this, &ParticipantListModel::setAdminStatus);
int row = mParticipants.count();
beginInsertRows(QModelIndex(), row, row);
mParticipants << participant;
endInsertRows();
add(participant);
changed = true;
}else if(!(*itParticipant)->getParticipant() || (*itParticipant)->getParticipant() != dbParticipant){
(*itParticipant)->setParticipant(dbParticipant);
}else if(!itParticipant->objectCast<ParticipantModel>()->getParticipant() || itParticipant->objectCast<ParticipantModel>()->getParticipant() != dbParticipant){
itParticipant->objectCast<ParticipantModel>()->setParticipant(dbParticipant);
changed = true;
}
}
@ -236,26 +176,23 @@ void ParticipantListModel::updateParticipants () {
}
}
void ParticipantListModel::add (std::shared_ptr<ParticipantModel> participant){
int row = mParticipants.count();
void ParticipantListModel::add (QSharedPointer<ParticipantModel> participant){
int row = mList.count();
connect(this, &ParticipantListModel::deviceSecurityLevelChanged, participant.get(), &ParticipantModel::onDeviceSecurityLevelChanged);
connect(this, &ParticipantListModel::securityLevelChanged, participant.get(), &ParticipantModel::onSecurityLevelChanged);
connect(participant.get(),&ParticipantModel::updateAdminStatus, this, &ParticipantListModel::setAdminStatus);
beginInsertRows(QModelIndex(), row, row);
mParticipants << participant;
endInsertRows();
ProxyListModel::add(participant);
emit layoutChanged();
emit participantsChanged();
emit countChanged();
}
void ParticipantListModel::remove (ParticipantModel *model) {
QString address = model->getSipAddress();
int index = 0;
bool found = false;
auto itParticipant = mParticipants.begin() ;
while(!found && itParticipant != mParticipants.end()){
if( (*itParticipant)->getSipAddress() == address)
auto itParticipant = mList.begin() ;
while(!found && itParticipant != mList.end()){
if( itParticipant->objectCast<ParticipantModel>()->getSipAddress() == address)
found = true;
else{
++itParticipant;
@ -263,23 +200,20 @@ void ParticipantListModel::remove (ParticipantModel *model) {
}
}
if(found) {
beginRemoveRows(QModelIndex(), index, index);
mParticipants.erase(itParticipant);
endRemoveRows();
removeRow(index);
emit participantsChanged();
emit countChanged();
}
}
const std::shared_ptr<ParticipantModel> ParticipantListModel::getParticipant(const std::shared_ptr<const linphone::Address>& address) const{
const QSharedPointer<ParticipantModel> ParticipantListModel::getParticipant(const std::shared_ptr<const linphone::Address>& address) const{
if(address){
auto itParticipant = std::find_if(mParticipants.begin(), mParticipants.end(), [address] (const std::shared_ptr<ParticipantModel>& participant){
return participant->getParticipant()->getAddress()->weakEqual(address);
auto itParticipant = std::find_if(mList.begin(), mList.end(), [address] (const QSharedPointer<QObject>& participant){
return participant.objectCast<ParticipantModel>()->getParticipant()->getAddress()->weakEqual(address);
});
if( itParticipant == mParticipants.end())
if( itParticipant == mList.end())
return nullptr;
else
return *itParticipant;
return itParticipant->objectCast<ParticipantModel>();
}else
return nullptr;
}

View file

@ -24,17 +24,17 @@
#include <QSortFilterProxyModel>
#include "components/participant/ParticipantModel.hpp"
#include "components/chat-room/ChatRoomModel.hpp"
#include "app/proxyModel/ProxyListModel.hpp"
// =============================================================================
class ParticipantListModel : public QAbstractListModel {
class ParticipantListModel : public ProxyListModel {
Q_OBJECT
public:
ParticipantListModel (ChatRoomModel * chatRoomModel, QObject *parent = Q_NULLPTR);
virtual ~ParticipantListModel();
Q_PROPERTY(ChatRoomModel* chatRoomModel READ getChatRoomModel CONSTANT)
Q_PROPERTY(int count READ getCount NOTIFY countChanged)
Q_PROPERTY(QString addressesToString READ addressesToString NOTIFY participantsChanged)
Q_PROPERTY(QString displayNamesToString READ displayNamesToString NOTIFY participantsChanged)
Q_PROPERTY(QString usernamesToString READ usernamesToString NOTIFY participantsChanged)
@ -42,20 +42,13 @@ public:
void reset();
void update();
void selectAll(const bool& selected);
ParticipantModel * getAt(const int& index);
const std::shared_ptr<ParticipantModel> getParticipant(const std::shared_ptr<const linphone::Address>& address) const;
const QSharedPointer<ParticipantModel> getParticipant(const std::shared_ptr<const linphone::Address>& address) const;
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;
void add (std::shared_ptr<ParticipantModel> participant);
void add (QSharedPointer<ParticipantModel> participant);
void updateParticipants(); // Update list from Chat Room
// Remove a chatroom
Q_INVOKABLE void remove (ParticipantModel *importer);
Q_INVOKABLE ChatRoomModel* getChatRoomModel() const;
int getCount() const;
std::list<std::shared_ptr<linphone::Address>> getParticipants()const;
Q_INVOKABLE QString addressesToString()const;
@ -64,8 +57,6 @@ public:
bool contains(const QString& address) const;
public slots:
void setAdminStatus(const std::shared_ptr<linphone::Participant> participant, const bool& isAdmin);
@ -83,14 +74,9 @@ signals:
void securityLevelChanged();
void deviceSecurityLevelChanged(std::shared_ptr<const linphone::Address> device);
void participantsChanged();
void countChanged();
private:
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
QList<std::shared_ptr<ParticipantModel>> mParticipants;
ChatRoomModel* mChatRoomModel;
};
Q_DECLARE_METATYPE(std::shared_ptr<ParticipantListModel>);
Q_DECLARE_METATYPE(QSharedPointer<ParticipantListModel>);
#endif // PARTICIPANT_LIST_MODEL_H_

View file

@ -37,7 +37,7 @@ ParticipantModel::ParticipantModel (shared_ptr<linphone::Participant> linphonePa
mAdminStatus = false;
if(mParticipant){
mAdminStatus = mParticipant->isAdmin();
mParticipantDevices = std::make_shared<ParticipantDeviceListModel>(mParticipant);
mParticipantDevices = QSharedPointer<ParticipantDeviceListModel>::create(mParticipant);
connect(this, &ParticipantModel::deviceSecurityLevelChanged, mParticipantDevices.get(), &ParticipantDeviceListModel::securityLevelChanged);
}
}
@ -54,7 +54,7 @@ int ParticipantModel::getSecurityLevel() const{
int ParticipantModel::getDeviceCount(){
int count = (mParticipant ? mParticipant->getDevices().size() : 0);
if(mParticipant && count != mParticipantDevices->count()){
if(mParticipant && count != mParticipantDevices->getCount()){
mParticipantDevices->updateDevices(mParticipant);
}
return count;
@ -108,7 +108,7 @@ void ParticipantModel::setParticipant(std::shared_ptr<linphone::Participant> par
mParticipant = participant;
if(mParticipant){
mAdminStatus = mParticipant->isAdmin();
mParticipantDevices = std::make_shared<ParticipantDeviceListModel>(mParticipant);
mParticipantDevices = QSharedPointer<ParticipantDeviceListModel>::create(mParticipant);
connect(this, &ParticipantModel::deviceSecurityLevelChanged, mParticipantDevices.get(), &ParticipantDeviceListModel::securityLevelChanged);
}
emit invitingChanged();
@ -132,7 +132,7 @@ ParticipantDeviceProxyModel * ParticipantModel::getProxyDevices(){
return devices;
}
std::shared_ptr<ParticipantDeviceListModel> ParticipantModel::getParticipantDevices(){
QSharedPointer<ParticipantDeviceListModel> ParticipantModel::getParticipantDevices(){
return mParticipantDevices;
}

View file

@ -27,6 +27,7 @@
#include <QObject>
#include <QDateTime>
#include <QString>
#include <QSharedPointer>
class ContactModel;
class ParticipantDeviceProxyModel;
@ -66,7 +67,7 @@ public:
std::shared_ptr<linphone::Participant> getParticipant();
Q_INVOKABLE ParticipantDeviceProxyModel * getProxyDevices();
std::shared_ptr<ParticipantDeviceListModel> getParticipantDevices();
QSharedPointer<ParticipantDeviceListModel> getParticipantDevices();
//linphone::ChatRoomSecurityLevel getSecurityLevel() const;
//std::shared_ptr<linphone::ParticipantDevice> findDevice(const std::shared_ptr<const linphone::Address> & address) const;
@ -95,7 +96,7 @@ signals:
private:
std::shared_ptr<linphone::Participant> mParticipant;
std::shared_ptr<ParticipantDeviceListModel> mParticipantDevices;
QSharedPointer<ParticipantDeviceListModel> mParticipantDevices;
// Variables when Linphone Participant has not been created
QString mSipAddress;
@ -103,6 +104,6 @@ private:
};
//Q_DECLARE_METATYPE(ParticipantModel *);
Q_DECLARE_METATYPE(std::shared_ptr<ParticipantModel>);
Q_DECLARE_METATYPE(QSharedPointer<ParticipantModel>);
#endif // PARTICIPANT_MODEL_H_

View file

@ -53,7 +53,7 @@ QStringList ParticipantProxyModel::getSipAddresses() const{
QStringList participants;
ParticipantListModel * list = qobject_cast<ParticipantListModel*>(sourceModel());
for(int i = 0 ; i < list->rowCount() ; ++i)
participants << list->getAt(i)->getSipAddress();
participants << list->getAt<ParticipantModel>(i)->getSipAddress();
return participants;
}
@ -83,7 +83,7 @@ void ParticipantProxyModel::setChatRoomModel(ChatRoomModel * chatRoomModel){
setSourceModel(participants);
emit participantListModelChanged();
for(int i = 0 ; i < participants->getCount() ; ++i)
emit addressAdded(participants->getAt(i)->getSipAddress());
emit addressAdded(participants->getAt<ParticipantModel>(i)->getSipAddress());
}else {
setSourceModel(new ParticipantListModel(nullptr, this));
emit participantListModelChanged();
@ -104,7 +104,7 @@ void ParticipantProxyModel::setShowMe(const bool& show){
void ParticipantProxyModel::addAddress(const QString& address){
ParticipantListModel * participantsModel = qobject_cast<ParticipantListModel*>(sourceModel());
if(!participantsModel->contains(address)){
std::shared_ptr<ParticipantModel> participant = std::make_shared<ParticipantModel>(nullptr);
QSharedPointer<ParticipantModel> participant = QSharedPointer<ParticipantModel>::create(nullptr);
participant->setSipAddress(address);
participantsModel->add(participant);
if(mChatRoomModel && mChatRoomModel->getChatRoom()){// Invite and wait for its creation

View file

@ -49,7 +49,7 @@ RecorderModel* RecorderManager::getVocalRecorder(){
params->setVideoCodec("");
auto recorder = core->createRecorder(params);
if(recorder)
mVocalRecorder = RecorderModel::create(recorder, this);
mVocalRecorder = RecorderModel::create(recorder, nullptr);
emit haveVocalRecorderChanged();
}
return mVocalRecorder.get();

View file

@ -53,6 +53,8 @@ TimelineListModel::TimelineListModel (QObject *parent) : ProxyListModel(parent)
updateTimelines ();
}
TimelineListModel::~TimelineListModel(){
}
// -----------------------------------------------------------------------------
void TimelineListModel::reset(){

View file

@ -39,7 +39,7 @@ public:
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
TimelineListModel (QObject *parent = Q_NULLPTR);
virtual ~TimelineListModel();
void reset();
void selectAll(const bool& selected);
TimelineModel * getAt(const int& index);

View file

@ -121,7 +121,8 @@ TimelineModel::TimelineModel (std::shared_ptr<linphone::ChatRoom> chatRoom, QObj
}
TimelineModel::~TimelineModel(){
//mChatRoomModel->getChatRoom()->removeListener(mChatRoomModel);
if( mChatRoomModel->getChatRoom())
mChatRoomModel->getChatRoom()->removeListener(mChatRoomListener);
}
QString TimelineModel::getFullPeerAddress() const{
@ -163,6 +164,9 @@ void TimelineModel::setSelected(const bool& selected){
<< ", canHandleParticipants:"<< mChatRoomModel->canHandleParticipants()
<< ", isReadOnly:" << mChatRoomModel->isReadOnly()
<< ", state:" << mChatRoomModel->getState();
QQmlEngine *engine = App::getInstance()->getEngine();
engine->clearComponentCache();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
}else
mChatRoomModel->resetData();// Cleanup leaving chat room
emit selectedChanged(mSelected);

View file

@ -152,7 +152,7 @@ public:
#ifdef Q_PROCESSOR_X86_64
static constexpr char PluginUrlH264[] = "http://ciscobinary.openh264.org/libopenh264-2.1.0-linux64.5.so.bz2";
#else
static constexpr char PluginUrlH264[] = "http://ciscobinary.openh264.org/libopenh264-2.1-0-linux32.5.so.bz2";
static constexpr char PluginUrlH264[] = "http://ciscobinary.openh264.org/libopenh264-2.1.0-linux32.5.so.bz2";
#endif // ifdef Q_PROCESSOR_X86_64
#elif defined(Q_OS_WIN)
static constexpr char LibraryExtension[] = "dll";

View file

@ -4,6 +4,7 @@ import QtQuick.Layouts 1.3
import Common.Styles 1.0
// =============================================================================
// modelData : {placeholder, text}
RowLayout {
id: form

View file

@ -82,7 +82,6 @@ ListView {
Repeater {
model: params ? params.actions : []
DropDownStaticMenuEntry {
entryName: modelData.name
Component.onCompleted: if( menu.maxWidth < implicitWidth ) menu.maxWidth = implicitWidth
@ -130,7 +129,7 @@ ListView {
// -------------------------------------------------------------------------
function useColorStatus () {
return calls.currentIndex === index && modelData && modelData.status !== CallModel.CallStatusEnded
return calls.currentIndex === index && $modelData && $modelData.status !== CallModel.CallStatusEnded
}
// -------------------------------------------------------------------------
@ -150,13 +149,13 @@ ListView {
return params ? 'call_sign_' + params.string : ''
}
entry: modelData
entry: $modelData
width: calls.width
onClicked: {
if (modelData.status !== CallModel.CallStatusEnded) {
Logic.updateSelectedCall(modelData, index)
if ($modelData.status !== CallModel.CallStatusEnded) {
Logic.updateSelectedCall($modelData, index)
}
}
@ -167,9 +166,9 @@ ListView {
readonly property int callId: index
readonly property var call: modelData
readonly property var call: $modelData
readonly property var callControls: _callControls
readonly property var params: Logic.getParams(modelData)
readonly property var params: Logic.getParams($modelData)
anchors.centerIn: parent
sourceComponent: params ? params.component : null
@ -177,7 +176,7 @@ ListView {
SequentialAnimation on color {
loops: CallsStyle.entry.endCallAnimation.loops
running: !modelData || modelData.status === CallModel.CallStatusEnded
running: !$modelData || $modelData.status === CallModel.CallStatusEnded
ColorAnimation {
duration: CallsStyle.entry.endCallAnimation.duration

View file

@ -56,7 +56,7 @@ Loader{
delegate:Text{
height: ChatStyle.composingText.height-5
width: GridView.width
text: deliveryLayout.getText(modelData.state, modelData.displayName, UtilsCpp.toDateTimeString(modelData.stateChangeTime))
text: deliveryLayout.getText($modelData.state, $modelData.displayName, UtilsCpp.toDateTimeString($modelData.stateChangeTime))
color: ChatStyle.entry.event.text.color
font.pointSize: Units.dp * 8
elide: Text.ElideMiddle

View file

@ -50,11 +50,11 @@ Item{
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: 7
//anchors.horizontalCenter: parent.horizontalCenter
thumbnail: modelData.thumbnail
name: modelData.name
thumbnail: $modelData.thumbnail
name: $modelData.name
animationScale: 1.1
onClickOnFile: {
modelData.openFile()
$modelData.openFile()
}
ActionButton{
anchors.bottom: parent.top
@ -66,7 +66,7 @@ Item{
colorSet: ChatFilePreviewStyle.filePreview.removeButton
z: parent.z+1
onClicked:{
contents.remove(modelData)
contents.remove($modelData)
}
}
}

View file

@ -141,10 +141,10 @@ Item {
//height: contentHeight
delegate: ChatContent{
contentModel: modelData
contentModel: $modelData
textColor: ChatReplyMessageStyle.replyArea.foregroundColor
textFont.pointSize: Units.dp * (customFont.pointSize + ChatReplyMessageStyle.replyArea.pointSizeOffset)
textFont.weight: Font.Light
//textFont.pointSize: Units.dp * (customFont.pointSize + ChatReplyMessageStyle.replyArea.pointSizeOffset)
//textFont.weight: Font.Light
onFitWidthChanged:{
replyMessage.updateWidth()
}

View file

@ -91,8 +91,8 @@ Rectangle{
height: contentHeight
delegate: ChatContent{
contentModel: modelData
textFont.pointSize: Units.dp * (SettingsModel.textMessageFont.pointSize - 2)
contentModel: $modelData
//textFont.pointSize: Units.dp * (SettingsModel.textMessageFont.pointSize - 2)
Rectangle{
anchors.left: parent.left
anchors.right: parent.right

View file

@ -105,7 +105,7 @@ Item {
delegate:
ChatContent{
maxWidth: container.width
contentModel: modelData
contentModel: $modelData
onFitWidthChanged:{
rectangle.updateWidth()
}

View file

@ -363,7 +363,7 @@ Rectangle {
Contact {
id: contactView
property bool isSelected: modelData != undefined && modelData.selected //view.currentIndex === index
property bool isSelected: $modelData != undefined && $modelData.selected //view.currentIndex === index
anchors.fill: parent
color: isSelected
@ -374,7 +374,7 @@ Rectangle {
: TimelineStyle.contact.backgroundColor.b
)
displayUnreadMessageCount: SettingsModel.standardChatEnabled || SettingsModel.secureChatEnabled
entry: modelData.chatRoomModel
entry: $modelData.chatRoomModel
sipAddressColor: isSelected
? TimelineStyle.contact.sipAddress.color.selected
: TimelineStyle.contact.sipAddress.color.normal
@ -383,18 +383,18 @@ Rectangle {
: TimelineStyle.contact.username.color.normal
TooltipArea {
id: contactTooltip
text: UtilsCpp.toDateTimeString(modelData.chatRoomModel.lastUpdateTime)
text: UtilsCpp.toDateTimeString($modelData.chatRoomModel.lastUpdateTime)
isClickable: true
}
Icon{
icon: TimelineStyle.ephemeralTimer.icon
iconSize: TimelineStyle.ephemeralTimer.iconSize
overwriteColor: modelData && modelData.selected ? TimelineStyle.ephemeralTimer.selectedTimerColor : TimelineStyle.ephemeralTimer.timerColor
overwriteColor: $modelData && $modelData.selected ? TimelineStyle.ephemeralTimer.selectedTimerColor : TimelineStyle.ephemeralTimer.timerColor
anchors.right:parent.right
anchors.bottom:parent.bottom
anchors.bottomMargin: 7
anchors.rightMargin: 7
visible: modelData.chatRoomModel.ephemeralEnabled
visible: $modelData.chatRoomModel.ephemeralEnabled
}
}
@ -405,11 +405,11 @@ Rectangle {
preventStealing: false
onClicked: {
if(mouse.button == Qt.LeftButton){
//if(modelData.selected || !view.updateSelectionModels)// Update selection
timeline.entryClicked(modelData)
//if($modelData.selected || !view.updateSelectionModels)// Update selection
timeline.entryClicked($modelData)
if(view){
if(view.updateSelectionModels)
modelData.selected = true
$modelData.selected = true
view.currentIndex = index;
}
}else{
@ -419,8 +419,9 @@ Rectangle {
}
Connections{
target:modelData
target:$modelData
onSelectedChanged:{
gc()
if(view.updateSelectionModels && selected) {
view.currentIndex = index;
}

View file

@ -128,7 +128,7 @@ ScrollableListView {
Icon{
visible: modelData.secure>0 &&
(sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler({sipAddres:$sipAddress}) : true)
icon:modelData.secure === 2?'secure_level_2':'secure_level_1'
icon: modelData.secure === 2?'secure_level_2':'secure_level_1'
iconSize:parent.height/2
anchors.top:parent.top
anchors.horizontalCenter: parent.right
@ -239,9 +239,9 @@ ScrollableListView {
showContactAddress: sipAddressesView.showContactAddress
//: '(Admin)' : One word for Admin(istrator)
//~ Context Little Header in one word for a column in participant
statusText : showAdminStatus && modelData.adminStatus ? qsTr('participantsAdminHeader') : ''
statusText : showAdminStatus && $modelData.adminStatus ? qsTr('participantsAdminHeader') : ''
entry: modelData
entry: $modelData
onAvatarClicked: sipAddressesView.entryClicked(parent.entry, index, contactView)
@ -250,7 +250,7 @@ ScrollableListView {
anchors.horizontalCenter: parent.horizontalCenter
width:15
height:15
running: sipAddressesView.showInvitingIndicator && modelData.inviting
running: sipAddressesView.showInvitingIndicator && $modelData.inviting
}
}
@ -272,9 +272,9 @@ ScrollableListView {
visible: sipAddressesView.showSwitch
enabled:true
checked: modelData.adminStatus
checked: $modelData.adminStatus
onClicked: {
modelData.adminStatus = !checked
$modelData.adminStatus = !checked
}
}
@ -286,7 +286,7 @@ ScrollableListView {
backgroundRadius: 90
colorSet: modelData.colorSet
anchors.verticalCenter: parent.verticalCenter
tooltipText:modelData.tooltipText?modelData.tooltipText:''
tooltipText: modelData.tooltipText? modelData.tooltipText:''
visible: sipAddressesView.actions[index].visible
onClicked: {
sipAddressesView.actions[index].handler(contactView.entry)
@ -294,7 +294,7 @@ ScrollableListView {
Icon{
visible: modelData.secure>0 &&
(sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler({sipAddres:$sipAddress}) : true)
icon:modelData.secure === 2?'secure_level_2':'secure_level_1'
icon: modelData.secure === 2?'secure_level_2':'secure_level_1'
iconSize: parent.height/2
anchors.top:parent.top
anchors.horizontalCenter: parent.right

View file

@ -208,7 +208,7 @@ ScrollableListView {
delegate: Rectangle {
id: sipAddressEntry
property var entry: modelData
property var entry: $modelData
color: SipAddressesViewStyle.entry.color.normal
height: SipAddressesViewStyle.entry.height
@ -245,11 +245,11 @@ ScrollableListView {
Layout.fillWidth: true
showContactAddress: sipAddressesView.showContactAddress
entry: modelData
entry: $modelData
MouseArea {
anchors.fill: parent
onClicked: sipAddressesView.entryClicked(modelData, index)
onClicked: sipAddressesView.entryClicked($modelData, index)
}
}
@ -291,15 +291,15 @@ ScrollableListView {
ActionButton {
isCustom: true
backgroundRadius: 90
colorSet: modelData.colorSet
tooltipText:modelData.tooltipText?modelData.tooltipText:''
visible: modelData.visible
onClicked: {// Do not use modelData on functions : Qt bug
colorSet: $modelData.colorSet
tooltipText:$modelData.tooltipText?$modelData.tooltipText:''
visible: $modelData.visible
onClicked: {// Do not use $modelData on functions : Qt bug
sipAddressesView.actions[index].handler(sipAddressEntry.entry)
}
Icon{
visible: modelData.secure>0 &&
// Do not use modelData on functions : Qt bug
visible: $modelData.secure>0 &&
// Do not use $modelData on functions : Qt bug
(sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler(sipAddressEntry.entry) : true)
icon: 'secure_on'
iconSize: parent.height/2

View file

@ -120,8 +120,8 @@ Rectangle {
width: grid.cellWidth
Column {
readonly property string sipAddress: modelData.peerAddress
property var _sipAddressObserver : SipAddressesModel.getSipAddressObserver(modelData.peerAddress, modelData.localAddress)
readonly property string sipAddress: $modelData.peerAddress
property var _sipAddressObserver : SipAddressesModel.getSipAddressObserver($modelData.peerAddress, $modelData.localAddress)
anchors {
fill: parent
@ -148,7 +148,7 @@ Rectangle {
)
anchors.horizontalCenter: parent.horizontalCenter
call: modelData
call: $modelData
onCallChanged: if(!call) conference.conferenceModel.invalidate()
height: size
@ -164,7 +164,7 @@ Rectangle {
height: CallStyle.header.busyIndicator.height
width: CallStyle.header.busyIndicator.width
visible: modelData && modelData.status === CallModel.CallStatusOutgoing
visible: $modelData && $modelData.status === CallModel.CallStatusOutgoing
}
}
}
@ -176,18 +176,18 @@ Rectangle {
leftMargin: ConferenceStyle.grid.spacing
bottomMargin: ConferenceStyle.grid.spacing
}
enabled:!modelData.speakerMuted
enabled:!$modelData.speakerMuted
Timer {
interval: 50
repeat: true
running: true
onTriggered: parent.value = modelData.speakerVu
onTriggered: parent.value = $modelData.speakerVu
}
}
MouseArea{
anchors.fill:parent
onClicked:modelData.toggleSpeakerMute()
onClicked:$modelData.toggleSpeakerMute()
}
}
}

View file

@ -172,7 +172,7 @@ Rectangle {
onCurrentDeviceChanged: console.log("currentDevice changed: " +currentDevice +", me:"+currentDevice.isMe+" ["+index+"]")
color: /*!conference.callModel && gridModel.defaultList.get(index).color ? gridModel.defaultList.get(index).color : */'#AAAAAAAA'
//color: gridModel.model.get(index) && gridModel.model.get(index).color ? gridModel.model.get(index).color : '' // modelIndex is a custom index because by Mosaic modelisation, it is not accessible.
//color: modelData.color ? modelData.color : ''
//color: $modelData.color ? $modelData.color : ''
radius: grid.radius
height: grid.cellHeight - 5
width: grid.cellWidth - 5

View file

@ -149,7 +149,7 @@ ColumnLayout {
//anchors.fill: parent
cellWidth: (container.width-20)/2
cellHeight: 100
model: modelData
model: $modelData
height: cellHeight * ( (count+1) /2)
width: container.width - 20
delegate:Rectangle {
@ -162,7 +162,7 @@ ColumnLayout {
border.width: ConferencesStyle.conference.selectedBorder.width
ChatCalendarMessage{
id: calendarMessage
conferenceInfoModel: modelData
conferenceInfoModel: $modelData
width: calendarGrid.cellWidth
maxWidth: calendarGrid.cellWidth
}

View file

@ -109,7 +109,7 @@ ColumnLayout {
PresenceLevel {
Layout.preferredHeight: ContactsStyle.contact.presenceLevelSize
Layout.preferredWidth: ContactsStyle.contact.presenceLevelSize
level: modelData.presenceLevel
level: $modelData.presenceLevel
}
Text {
@ -117,7 +117,7 @@ ColumnLayout {
color: ContactsStyle.contact.presence.color
elide: Text.ElideRight
font.pointSize: ContactsStyle.contact.presence.pointSize
text: Presence.getPresenceStatusAsString(modelData.presenceStatus)
text: Presence.getPresenceStatusAsString($modelData.presenceStatus)
}
}
}
@ -189,7 +189,7 @@ ColumnLayout {
verticalCenter: parent.verticalCenter
}
onClicked: _removeContact(modelData)
onClicked: _removeContact($modelData)
}
}
}
@ -199,6 +199,7 @@ ColumnLayout {
Repeater {
id: actions
property ChatRoomModel lastChatRoom
property ContactModel contactModel: $modelData
Connections{
target: lastChatRoom
@ -222,8 +223,7 @@ ColumnLayout {
SipAddressesMenu {
relativeTo: loader
relativeY: loader.height
sipAddresses: modelData.vcard.sipAddresses
sipAddresses: actions.contactModel.vcard.sipAddresses
onSipAddressClicked: actions.handlers[index](sipAddress)
}
@ -250,7 +250,7 @@ ColumnLayout {
anchors.fill: parent
onClicked: window.setView('ContactEdit', {
sipAddress: modelData.vcard.sipAddresses[0]
sipAddress: $modelData.vcard.sipAddresses[0]
})
}
@ -269,8 +269,8 @@ ColumnLayout {
Avatar {
anchors.centerIn: parent
image: modelData.vcard.avatar
username: modelData.vcard.username
image: $modelData.vcard.avatar
username: $modelData.vcard.username
height: ContactsStyle.contact.avatarSize
width: ContactsStyle.contact.avatarSize
@ -289,7 +289,7 @@ ColumnLayout {
pointSize: ContactsStyle.contact.username.pointSize
}
text: modelData.vcard.username
text: $modelData.vcard.username
verticalAlignment: Text.AlignVCenter
}

View file

@ -216,13 +216,13 @@ DialogPlus {
Layout.preferredHeight: 50
Layout.preferredWidth: 50
Layout.alignment: Qt.AlignCenter
username: modelData.username
image:modelData.avatar
username: $modelData.username
image:$modelData.avatar
Icon{
property int securityLevel : 2
anchors.top:parent.top
anchors.horizontalCenter: parent.right
visible: UtilsCpp.hasCapability(modelData.sipAddress, LinphoneEnums.FriendCapabilityLimeX3Dh)
visible: UtilsCpp.hasCapability($modelData.sipAddress, LinphoneEnums.FriendCapabilityLimeX3Dh)
icon: 'secure_on'
iconSize: parent.height/2
}
@ -233,7 +233,7 @@ DialogPlus {
Layout.alignment: Qt.AlignVCenter | Qt.AlignTop
maximumLineCount: 5
wrapMode:Text.Wrap
text: modelData.username
text: $modelData.username
verticalAlignment: Text.AlignTop
horizontalAlignment: Text.AlignHCenter
@ -251,11 +251,11 @@ DialogPlus {
anchors.topMargin: -5
color:'white'
opacity: 0.5
visible: smartSearchBar.isIgnored(modelData.sipAddress)
visible: smartSearchBar.isIgnored($modelData.sipAddress)
Connections{// Workaround for refreshing data on events
target:lastContacts
onReloadCountChanged: {
mask.visible=smartSearchBar.isIgnored(modelData.sipAddress)
mask.visible=smartSearchBar.isIgnored($modelData.sipAddress)
}
}
}
@ -263,8 +263,8 @@ DialogPlus {
anchors.fill:parent
visible:!mask.visible
onClicked: {
selectedParticipants.addAddress(modelData.sipAddress)
smartSearchBar.addAddressToIgnore(modelData.sipAddress);
selectedParticipants.addAddress($modelData.sipAddress)
smartSearchBar.addAddressToIgnore($modelData.sipAddress);
++lastContacts.reloadCount
}
}

View file

@ -50,8 +50,8 @@ DialogPlus {
ColumnLayout{
id:mainHeader
property var window : ListView.view.window
property int securityLevel : modelData.securityLevel
property string addressToCall : modelData.sipAddress
property int securityLevel : $modelData.securityLevel
property string addressToCall : $modelData.sipAddress
width: parent ? parent.width : undefined
spacing: 0
@ -66,19 +66,19 @@ DialogPlus {
Layout.preferredHeight: 32
Layout.preferredWidth: 32
Layout.leftMargin: 14
username: modelData?(modelData.contactModel ? modelData.contactModel.vcard.username
:modelData.username?modelData.username:
UtilsCpp.getDisplayName(modelData.sipAddress)
username: $modelData?($modelData.contactModel ? $modelData.contactModel.vcard.username
:$modelData.username?$modelData.username:
UtilsCpp.getDisplayName($modelData.sipAddress)
):''
Icon{
property int securityLevel : modelData.securityLevel
property int securityLevel : $modelData.securityLevel
anchors.top:parent.top
anchors.horizontalCenter: parent.right
visible: modelData && securityLevel !== 1
icon: modelData?(securityLevel === 2?'secure_level_1': securityLevel===3? 'secure_level_2' : 'secure_level_unsafe'):'secure_level_unsafe'
visible: $modelData && securityLevel !== 1
icon: $modelData?(securityLevel === 2?'secure_level_1': securityLevel===3? 'secure_level_2' : 'secure_level_unsafe'):'secure_level_unsafe'
iconSize: parent.height/2
Timer{// Workaround : no security events are send when device's security change.
onTriggered: parent.securityLevel = modelData.securityLevel
onTriggered: parent.securityLevel = $modelData.securityLevel
repeat:true
running:true
interval:500
@ -113,21 +113,21 @@ DialogPlus {
Layout.preferredWidth: iconSize
Layout.leftMargin: isCustom ? 9 : 14
Layout.rightMargin: isCustom ? 9 : 14
property int securityLevel : modelData.securityLevel
property int securityLevel : $modelData.securityLevel
property bool participantsDevicesVisible: participantDevices.visible
function setColorSet(){
if(isCustom)
colorSet = participantsDevicesVisible ? ParticipantsDevicesStyle.expanded : ParticipantsDevicesStyle.collapsed
iconSize = colorSet.iconSize
}
onSecurityLevelChanged: if( modelData.deviceCount == 0){
onSecurityLevelChanged: if( $modelData.deviceCount == 0){
icon = securityLevel === 2?'secure_level_1':
(securityLevel===3? 'secure_level_2' : 'secure_level_unsafe')
iconSize = 20
}
onParticipantsDevicesVisibleChanged: setColorSet()
visible:true
useStates: modelData.deviceCount > 0
useStates: $modelData.deviceCount > 0
isCustom: useStates
onIsCustomChanged: setColorSet()
onClicked: participantDevices.visible = !participantDevices.visible
@ -149,7 +149,7 @@ DialogPlus {
Layout.preferredHeight: item.height * count
interactive: false
model: modelData.getProxyDevices()
model: $modelData.getProxyDevices()
delegate: Rectangle{
id:mainRectangle
@ -172,7 +172,7 @@ DialogPlus {
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap
text:modelData.name
text: modelData.name
MouseArea{
anchors.fill:parent
@ -193,7 +193,7 @@ DialogPlus {
icon: securityLevel === 2?'secure_level_1': securityLevel===3? 'secure_level_2' : 'secure_level_unsafe'
iconSize:20
Timer{// Workaround : no security events are send when device's security change.
onTriggered: parent.securityLevel = modelData.securityLevel
onTriggered: parent.securityLevel = $modelData.securityLevel
repeat:true
running:true
interval:500

View file

@ -151,8 +151,8 @@ TabContainer {
disableLineTitle:true
FormTableLine {
id:importerLine
property var fields : modelData.fields
property int identity : modelData.identity
property var fields : $modelData.fields
property int identity : $modelData.identity
property var pluginDescription : ContactsImporterPluginsManager.getContactsImporterPluginDescription(fields["pluginID"]) // Plugin definition
FormTableEntry {
@ -163,7 +163,7 @@ TabContainer {
isCustom: true
backgroundRadius: 90
colorSet: SettingsAdvancedStyle.cancel
onClicked:ContactsImporterListModel.removeContactsImporter(modelData)
onClicked:ContactsImporterListModel.removeContactsImporter($modelData)
}
Text{
height:parent.height
@ -188,7 +188,7 @@ TabContainer {
model:importerLine.pluginDescription['fields']
delegate: FormTableEntry {
Loader{
sourceComponent: (modelData['type']==0 ? textComponent:textFieldComponent)
sourceComponent: ($modelData['type']==0 ? textComponent:textFieldComponent)
active:true
width:parent.width
Component{
@ -197,7 +197,7 @@ TabContainer {
color: FormTableStyle.entry.text.color
elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter
text: importerLine.fields[modelData['fieldId']]?importerLine.fields[modelData['fieldId']]:''
text: importerLine.fields[$modelData['fieldId']]?importerLine.fields[$modelData['fieldId']]:''
height: FormTableStyle.entry.height
width: parent.width
font {
@ -211,13 +211,13 @@ TabContainer {
TextField {
readOnly: false
width:parent.width
placeholderText : modelData['placeholder']
text: importerLine.fields[modelData['fieldId']]?importerLine.fields[modelData['fieldId']]:''
echoMode: (modelData['hiddenText']?TextInput.Password:TextInput.Normal)
placeholderText : $modelData['placeholder']
text: importerLine.fields[$modelData['fieldId']]?importerLine.fields[$modelData['fieldId']]:''
echoMode: ($modelData['hiddenText']?TextInput.Password:TextInput.Normal)
onEditingFinished:{
importerLine.fields[modelData['fieldId']] = text
importerLine.fields[$modelData['fieldId']] = text
}
Component.onCompleted: importerLine.fields[modelData['fieldId']] = text
Component.onCompleted: importerLine.fields[$modelData['fieldId']] = text
}
}
}
@ -225,7 +225,7 @@ TabContainer {
}// Repeater : Fields
FormTableEntry {
Switch {
checked: modelData.fields["enabled"]>0
checked: $modelData.fields["enabled"]>0
onClicked: {
checked = !checked
importerLine.fields["enabled"] = (checked?1:0)
@ -258,7 +258,7 @@ TabContainer {
pointSize: SettingsAdvancedStyle.info.pointSize
}
Connections{
target:modelData
target:$modelData
onStatusMessage:{contactsImporterStatus.isError=false;contactsImporterStatus.text=message;}
onErrorMessage:{contactsImporterStatus.isError=true;contactsImporterStatus.text=message;}
}

View file

@ -73,7 +73,7 @@ Column {
colorSet: SettingsAdvancedStyle.cancel
scale:SettingsAdvancedStyle.lists.iconScale
onClicked:{
LdapListModel.remove(modelData)
LdapListModel.remove($modelData)
}
visible:hoveringRow.containsMouse
}

View file

@ -81,7 +81,7 @@ TabContainer {
FormTable {
legendLineWidth: SettingsWindowStyle.sipAccounts.legendLineWidth
titles: [
titles: ['',
qsTr('editHeader'),
qsTr('deleteHeader')
]

View file

@ -189,18 +189,18 @@ TabContainer {
delegate:
Form {
//: 'Server' : Title form to set a server
title: qsTr('serverTitle')+' : '+modelData.host+(view.tunnelModel.dualModeEnabled?' / '+modelData.host2:'')
title: qsTr('serverTitle')+' : '+$modelData.host+(view.tunnelModel.dualModeEnabled?' / '+$modelData.host2:'')
width: view.width
removeButton: SettingsModel.developerSettingsEnabled
onRemoveButtonClicked: {view.tunnelModel.removeTunnelConfig(modelData)}
onRemoveButtonClicked: {view.tunnelModel.removeTunnelConfig($modelData)}
FormLine {
FormGroup {
//: 'Hostname' : Field title on form to set hostname.
label: qsTr('serverHostname')
TextField {
text: modelData.host
onEditingFinished: modelData.host = text
text: $modelData.host
onEditingFinished: $modelData.host = text
}
}
}
@ -209,8 +209,8 @@ TabContainer {
//: 'Port' : Field title on form to set port.
label: qsTr('serverPort')
NumericField {
text: modelData.port
onEditingFinished: modelData.port = text
text: $modelData.port
onEditingFinished: $modelData.port = text
maxValue: 65535
}
}
@ -221,8 +221,8 @@ TabContainer {
//: 'Dual hostname URL' : Field title on form to set the second hostname for dual configuration.
label: qsTr('serverDualHostname')
TextField {
text: modelData.host2
onEditingFinished: modelData.host2 = text
text: $modelData.host2
onEditingFinished: $modelData.host2 = text
}
}
}
@ -232,8 +232,8 @@ TabContainer {
//: 'Dual port' : Field title on form to set the second port for the dual configuration.
label: qsTr('serverDualPort')
NumericField {
text: modelData.port2
onEditingFinished: modelData.port2 = text
text: $modelData.port2
onEditingFinished: $modelData.port2 = text
maxValue: 65535
}
}
@ -245,8 +245,8 @@ TabContainer {
//: 'Remote UDP mirror port' : Field title on form to set the remote UDP mirror port.
label: qsTr('serverRemoteUDPMirrorPort')
NumericField {
text: modelData.remoteUdpMirrorPort
onEditingFinished: modelData.remoteUdpMirrorPort = text
text: $modelData.remoteUdpMirrorPort
onEditingFinished: $modelData.remoteUdpMirrorPort = text
maxValue: 65535
}
}
@ -257,8 +257,8 @@ TabContainer {
//: 'Delay' : Field title on form to set the delay of the tunnel.
label: qsTr('serverDelay')
NumericField {
text: modelData.delay
onEditingFinished: modelData.delay = text
text: $modelData.delay
onEditingFinished: $modelData.delay = text
}
}
}