This commit is contained in:
Julien Wadel 2022-04-15 18:13:00 +02:00
parent ce5ced320f
commit a541df0cd4
77 changed files with 1588 additions and 878 deletions

View file

@ -142,6 +142,7 @@ set(SOURCES
src/app/providers/ExternalImageProvider.cpp
src/app/providers/ThumbnailProvider.cpp
src/app/proxyModel/ProxyListModel.cpp
src/app/proxyModel/SortFilterProxyModel.cpp
#src/app/proxyModel/ProxyMapModel.cpp
#src/app/proxyModel/ProxyModel.cpp
src/app/translator/DefaultTranslator.cpp
@ -167,13 +168,16 @@ set(SOURCES
src/components/codecs/VideoCodecsModel.cpp
src/components/conference/ConferenceAddModel.cpp
src/components/conference/ConferenceHelperModel.cpp
src/components/conference/ConferenceListener.cpp
src/components/conference/ConferenceModel.cpp
src/components/conference/ConferenceProxyModel.cpp
src/components/conferenceInfo/ConferenceInfoModel.cpp
src/components/conferenceInfo/ConferenceInfoListModel.cpp
src/components/conferenceInfo/ConferenceInfoMapModel.cpp
src/components/conferenceInfo/ConferenceInfoProxyListModel.cpp
src/components/conferenceInfo/ConferenceInfoProxyModel.cpp
src/components/conferenceScheduler/ConferenceSchedulerHandler.cpp
src/components/conferenceScheduler/ConferenceScheduler.cpp
src/components/conferenceScheduler/ConferenceSchedulerListener.cpp
src/components/contact/ContactModel.cpp
src/components/contact/VcardModel.cpp
src/components/contacts/ContactsImporterModel.cpp
@ -220,7 +224,7 @@ set(SOURCES
src/components/presence/Presence.cpp
src/components/recorder/RecorderManager.cpp
src/components/recorder/RecorderModel.cpp
src/components/search/SearchHandler.cpp
src/components/search/SearchListener.cpp
src/components/search/SearchResultModel.cpp
src/components/search/SearchSipAddressesModel.cpp
src/components/search/SearchSipAddressesProxyModel.cpp
@ -263,7 +267,12 @@ set(HEADERS
src/app/providers/ImageProvider.hpp
src/app/providers/ExternalImageProvider.hpp
src/app/providers/ThumbnailProvider.hpp
src/app/proxyModel/ProxyAbstractListModel.hpp
src/app/proxyModel/ProxyAbstractMapModel.hpp
src/app/proxyModel/ProxyAbstractObject.hpp
src/app/proxyModel/ProxyListModel.hpp
src/app/proxyModel/SortFilterAbstractProxyModel.hpp
src/app/proxyModel/SortFilterProxyModel.hpp
#src/app/proxyModel/ProxyMapModel.hpp
#src/app/proxyModel/ProxyModel.hpp
src/app/single-application/SingleApplication.hpp
@ -291,13 +300,16 @@ set(HEADERS
src/components/Components.hpp
src/components/conference/ConferenceAddModel.hpp
src/components/conference/ConferenceHelperModel.hpp
src/components/conference/ConferenceListener.hpp
src/components/conference/ConferenceModel.hpp
src/components/conference/ConferenceProxyModel.hpp
src/components/conferenceInfo/ConferenceInfoModel.hpp
src/components/conferenceInfo/ConferenceInfoListModel.hpp
src/components/conferenceInfo/ConferenceInfoMapModel.hpp
src/components/conferenceInfo/ConferenceInfoProxyListModel.hpp
src/components/conferenceInfo/ConferenceInfoProxyModel.hpp
src/components/conferenceScheduler/ConferenceSchedulerHandler.hpp
src/components/conferenceScheduler/ConferenceScheduler.hpp
src/components/conferenceScheduler/ConferenceSchedulerListener.hpp
src/components/contact/ContactModel.hpp
src/components/contact/VcardModel.hpp
src/components/contacts/ContactsImporterModel.hpp
@ -345,7 +357,7 @@ set(HEADERS
src/components/presence/Presence.hpp
src/components/recorder/RecorderManager.hpp
src/components/recorder/RecorderModel.hpp
src/components/search/SearchHandler.hpp
src/components/search/SearchListener.hpp
src/components/search/SearchResultModel.hpp
src/components/search/SearchSipAddressesModel.hpp
src/components/search/SearchSipAddressesProxyModel.hpp

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="80"
height="80"
viewBox="0 0 80 80"
version="1.1"
id="svg4"
sodipodi:docname="conference_preview_custom.svg"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs8" />
<sodipodi:namedview
id="namedview6"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="true"
showgrid="false"
width="80px"
inkscape:zoom="9.2910448"
inkscape:cx="28.575904"
inkscape:cy="38.208835"
inkscape:window-width="1920"
inkscape:window-height="1043"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="m 1.823795,30.924684 v 12.88109 L 14.554044,33.725346 V 44.553512 H 49.378011 V 16.823795 H 14.554044 V 27.65196 L 1.823795,17.570312 Z M 78.1762,49.075312 V 36.194221 L 65.444739,46.274649 V 35.446483 H 30.621983 V 63.176201 H 65.444739 V 52.348035 L 78.1762,62.428464 Z"
stroke="#000000"
stroke-width="3.64759"
fill="none"
fill-rule="evenodd"
stroke-linecap="round"
stroke-linejoin="round"
id="path2" />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -29,6 +29,7 @@
<file>assets/images/call_sign_paused.svg</file>
<file>assets/images/camera_off_custom.svg</file>
<file>assets/images/camera_on_custom.svg</file>
<file>assets/images/camera_preview_custom.svg</file>
<file>assets/images/cancel_custom.svg</file>
<file>assets/images/chat_custom.svg</file>
<file>assets/images/chat_amount.svg</file>

View file

@ -237,6 +237,7 @@ App::~App () {
qInfo() << QStringLiteral("Destroying app...");
if( mEngine )
delete mEngine;
CoreManager::uninit();
processEvents(QEventLoop::AllEvents); // Process all needed events on engine deletion.
if( mParser)
delete mParser;

View file

@ -75,9 +75,11 @@ int main (int argc, char *argv[]) {
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();
if( CoreManager::getInstance()){
auto core = CoreManager::getInstance()->getCore();
if(core && core->getGlobalState() == linphone::GlobalState::On)
core->stop();
}
cleanStream();
return ret;
}

View file

@ -0,0 +1,108 @@
/*
* 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 PROXY_ABSTRACT_LIST_MODEL_H_
#define PROXY_ABSTRACT_LIST_MODEL_H_
#include <QAbstractListModel>
#include <QDebug>
#include "ProxyAbstractObject.hpp"
template <class T>
class ProxyAbstractListModel : public ProxyAbstractObject {
public:
ProxyAbstractListModel (QObject *parent = Q_NULLPTR) : ProxyAbstractObject(parent) {}
virtual ~ProxyAbstractListModel(){
resetData();
}
virtual int rowCount (const QModelIndex &index = QModelIndex()) const override{
return mList.count();
}
virtual QHash<int, QByteArray> roleNames () const override {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$modelData";
return roles;
}
virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override{
int row = index.row();
if (!index.isValid() || row < 0 || row >= mList.count())
return QVariant();
if (role == Qt::DisplayRole)
return QVariant::fromValue(mList[row]);
return QVariant();
}
virtual T getAt(const int& index) const{
return mList[index];
}
// Add functions
virtual void add(T item){
int row = mList.count();
beginInsertRows(QModelIndex(), row, row);
mList << item;
endInsertRows();
}
virtual void prepend(T item){
beginInsertRows(QModelIndex(), 0, 0);
mList.prepend(item);
endInsertRows();
}
virtual void prepend(QList<T> items){
beginInsertRows(QModelIndex(), 0, items.size()-1);
items << mList;
mList = items;
endInsertRows();
}
// Remove functions
virtual bool removeRow (int row, const QModelIndex &parent = QModelIndex()){
return removeRows(row, 1, parent);
}
virtual bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override{
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;
}
virtual void resetData(){
beginResetModel();
mList.clear();
endResetModel();
}
protected:
QList<T> mList;
};
#endif

View file

@ -0,0 +1,114 @@
/*
* 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 PROXY_ABSTRACT_MAP_MODEL_H_
#define PROXY_ABSTRACT_MAP_MODEL_H_
#include <QDebug>
#include "ProxyAbstractObject.hpp"
template <class X, class Y>
class ProxyAbstractMapModel : public ProxyAbstractObject {
public:
ProxyAbstractMapModel (QObject *parent = Q_NULLPTR) : ProxyAbstractObject(parent) {}
virtual ~ProxyAbstractMapModel(){
resetData();
}
virtual int rowCount (const QModelIndex &index = QModelIndex()) const override{
return mMappedList.count();
}
virtual QHash<int, QByteArray> roleNames () const override {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$modelData";
roles[Qt::DisplayRole+1] = "$modelKey";
return roles;
}
virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override{
int row = index.row();
auto it = mMappedList.begin() + row;
if (role == Qt::DisplayRole)
return QVariant::fromValue(*it);
else if( role == Qt::DisplayRole+1)
return QVariant::fromValue(it.key());
return QVariant();
}
/*
virtual Y getAt(const int& index) const{
mList.
return mList[index];
}*/
// Add functions
/*
virtual void add(T item){
int row = mList.count();
beginInsertRows(QModelIndex(), row, row);
mList << item;
endInsertRows();
}
virtual void prepend(T item){
beginInsertRows(QModelIndex(), 0, 0);
mList.prepend(item);
endInsertRows();
}
virtual void prepend(QList<T> items){
beginInsertRows(QModelIndex(), 0, items.size()-1);
items << mList;
mList = items;
endInsertRows();
}
// Remove functions
virtual bool removeRow (int row, const QModelIndex &parent = QModelIndex()){
return removeRows(row, 1, parent);
}
virtual bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override{
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;
}
*/
virtual void resetData(){
beginResetModel();
mMappedList.clear();
endResetModel();
}
protected:
QMap<X, Y> mMappedList;
};
#endif

View file

@ -0,0 +1,47 @@
/*
* 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 PROXY_ABSTRACT_OBJECT_H_
#define PROXY_ABSTRACT_OBJECT_H_
#include <QAbstractListModel>
#include <QDebug>
// Use a regular declaration for Qt signal/slots handling
class ProxyAbstractObject : public QAbstractListModel{
Q_OBJECT
public:
Q_PROPERTY(int count READ getCount NOTIFY countChanged)
ProxyAbstractObject(QObject * parent = nullptr) : QAbstractListModel(parent){
connect(this, &ProxyAbstractObject::rowsInserted, this, &ProxyAbstractObject::countChanged);
connect(this, &ProxyAbstractObject::rowsRemoved, this, &ProxyAbstractObject::countChanged);
}
Q_INVOKABLE virtual int getCount() const{
return rowCount();
}
Q_INVOKABLE virtual bool remove(QObject *itemToRemove){return false;}
Q_INVOKABLE virtual void resetData(){}
signals:
void countChanged();
};
#endif

View file

@ -24,45 +24,10 @@
// =============================================================================
ProxyListModel::ProxyListModel (QObject *parent) : QAbstractListModel(parent) {
connect(this, &ProxyListModel::rowsInserted, this, &ProxyListModel::countChanged);
connect(this, &ProxyListModel::rowsRemoved, this, &ProxyListModel::countChanged);
ProxyListModel::ProxyListModel (QObject *parent) : ProxyAbstractListModel(parent) {
}
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";
return roles;
}
QVariant ProxyListModel::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();
}
QSharedPointer<QObject> ProxyListModel::getAt(const int& index) const{
return mList[index];
}
QSharedPointer<QObject> ProxyListModel::get(QObject * itemToGet, int * index) const{
@ -78,25 +43,7 @@ QSharedPointer<QObject> ProxyListModel::get(QObject * itemToGet, int * index) co
}
// -----------------------------------------------------------------------------
void ProxyListModel::add(QSharedPointer<QObject> item){
int row = mList.count();
beginInsertRows(QModelIndex(), row, row);
mList << item;
endInsertRows();
}
void ProxyListModel::prepend(QSharedPointer<QObject> item){
mList.prepend(item);
}
void ProxyListModel::prepend(QList<QSharedPointer<QObject>> items){
beginInsertRows(QModelIndex(), 0, items.size()-1);
items << mList;
mList = items;
endInsertRows();
}
/*
bool ProxyListModel::remove(QObject *itemToRemove) {
bool removed = false;
qInfo() << QStringLiteral("Removing ") << itemToRemove->metaObject()->className() << QStringLiteral(" : ") << itemToRemove;
@ -110,35 +57,6 @@ bool ProxyListModel::remove(QObject *itemToRemove) {
if( !removed)
qWarning() << QStringLiteral("Unable to remove ") << itemToRemove->metaObject()->className() << QStringLiteral(" : ") << itemToRemove;
return removed;
}
}*/
bool ProxyListModel::remove(QSharedPointer<QObject> itemToRemove){
return remove(itemToRemove.get());
}
bool ProxyListModel::removeRow (int row, const QModelIndex &parent) {
return removeRows(row, 1, parent);
}
bool ProxyListModel::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 ProxyListModel::resetData(){
beginResetModel();
mList.clear();
endResetModel();
}
// -----------------------------------------------------------------------------

View file

@ -22,12 +22,12 @@
#define _PROXY_LIST_MODEL_H_
#include <QAbstractListModel>
#include "ProxyAbstractListModel.hpp"
#include <QSharedPointer>
// =============================================================================
class ProxyListModel : public QAbstractListModel {
class ProxyListModel : public ProxyAbstractListModel<QSharedPointer<QObject>> {
Q_OBJECT
public:
@ -35,16 +35,9 @@ public:
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>();
return ProxyAbstractListModel<QSharedPointer<QObject>>::getAt(index).objectCast<T>();
}
QSharedPointer<QObject> get(QObject * itemToGet, int * index = nullptr) const;
@ -57,20 +50,24 @@ public:
return newList;
}
// Add functions
virtual void add(QSharedPointer<QObject> item);
virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override{
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();
}
template <class T>
void add(QSharedPointer<T> item){
add(item.template objectCast<QObject>());
ProxyAbstractListModel<QSharedPointer<QObject>>::add(item.template objectCast<QObject>());
}
//virtual void add(QList<QSharedPointer<QObject>> item);
virtual void prepend(QSharedPointer<QObject> item);
template <class T>
void prepend(QSharedPointer<T> item){
prepend(item.template objectCast<QObject>());
ProxyAbstractListModel<QSharedPointer<QObject>>::prepend(item.template objectCast<QObject>());
}
virtual void prepend(QList<QSharedPointer<QObject>> items);
template <class T>
void prepend(QList<QSharedPointer<T>> items){
beginInsertRows(QModelIndex(), 0, items.size()-1);
@ -78,23 +75,24 @@ public:
mList = items;
endInsertRows();
}
// Remove functions
Q_INVOKABLE virtual bool remove(QObject *itemToRemove) ;
virtual bool remove(QSharedPointer<QObject> itemToRemove) ;
virtual bool removeRow (int row, const QModelIndex &parent = QModelIndex());
virtual bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
Q_INVOKABLE virtual void resetData();
signals:
void countChanged();
protected:
QList<QSharedPointer<QObject>> mList;
virtual bool remove(QObject *itemToRemove) override{
bool removed = false;
qInfo() << QStringLiteral("Removing ") << itemToRemove->metaObject()->className() << QStringLiteral(" : ") << itemToRemove;
int index = 0;
for(auto item : mList)
if( item == itemToRemove) {
removed = removeRow(index);
break;
}else
++index;
if( !removed)
qWarning() << QStringLiteral("Unable to remove ") << itemToRemove->metaObject()->className() << QStringLiteral(" : ") << itemToRemove;
return removed;
}
virtual bool remove(QSharedPointer<QObject> itemToRemove){
return remove(itemToRemove.get());
}
};
#endif

View file

@ -1,93 +0,0 @@
/*
* Copyright (c) 2021 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 "ConferenceInfoMapModel.hpp"
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include <QTimer>
#include "app/App.hpp"
#include "components/conference/ConferenceAddModel.hpp"
#include "components/conference/ConferenceHelperModel.hpp"
#include "components/core/CoreHandlers.hpp"
#include "components/core/CoreManager.hpp"
#include "components/settings/SettingsModel.hpp"
#include "utils/Utils.hpp"
#include "ConferenceInfoProxyModel.hpp"
#include "ConferenceInfoListModel.hpp"
#include "ConferenceInfoModel.hpp"
// =============================================================================
ConferenceInfoMapModel::ConferenceInfoMapModel (QObject *parent) : QAbstractListModel(parent) {
auto conferenceInfos = CoreManager::getInstance()->getCore()->getConferenceInformationList();
auto me = CoreManager::getInstance()->getCore()->getDefaultAccount()->getParams()->getIdentityAddress();
for(auto conferenceInfo : conferenceInfos){
std::list<std::shared_ptr<linphone::Address>> participants = conferenceInfo->getParticipants();
bool haveMe = conferenceInfo->getOrganizer()->weakEqual(me);
if(!haveMe)
haveMe = (std::find_if(participants.begin(), participants.end(), [me](const std::shared_ptr<linphone::Address>& address){
return me->weakEqual(address);
}) != participants.end());
if(haveMe){
auto conferenceInfoModel = ConferenceInfoModel::create( conferenceInfo );
QDate t = conferenceInfoModel->getDateTime().date();
if( !mMappedList.contains(t))
mMappedList[t] = new ConferenceInfoProxyModel(new ConferenceInfoListModel(), this);
mMappedList[t]->add(conferenceInfoModel);
}
}
}
int ConferenceInfoMapModel::rowCount (const QModelIndex &) const {
return mMappedList.size();
}
QHash<int, QByteArray> ConferenceInfoMapModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$modelData";
roles[Qt::DisplayRole + 1] = "date";
return roles;
}
QVariant ConferenceInfoMapModel::data (const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mMappedList.size())
return QVariant();
auto it = mMappedList.begin() + row;
if (role == Qt::DisplayRole)
return QVariant::fromValue(*it);
else if( role == Qt::DisplayRole+1)
return QVariant::fromValue(it.key());
return QVariant();
}
// -----------------------------------------------------------------------------
void ConferenceInfoMapModel::setConferenceInfoFilter (int filterMode){
for(auto list : mMappedList){
list->setConferenceInfoFilter(filterMode);
}
}

View file

@ -0,0 +1,41 @@
/*
* 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 SORT_FILTER_ABSTRACT_PROXY_MODEL_H_
#define SORT_FILTER_ABSTRACT_PROXY_MODEL_H_
#include "SortFilterProxyModel.hpp"
template <class T>
class SortFilterAbstractProxyModel : public SortFilterProxyModel {
public:
SortFilterAbstractProxyModel(T * model, QObject * parent = nullptr) : SortFilterProxyModel(parent){
setSourceModel(model);
sort(0, Qt::DescendingOrder);
}
template <class X>
void add(QSharedPointer<X> x){
qobject_cast<T*>(sourceModel())->add(x);
}
};
#endif

View file

@ -0,0 +1,47 @@
/*
* 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 "SortFilterProxyModel.hpp"
SortFilterProxyModel::SortFilterProxyModel(QObject * parent) : QSortFilterProxyModel(parent){
mFilterType = 0;
connect(this, &SortFilterProxyModel::rowsInserted, this, &SortFilterProxyModel::countChanged);
connect(this, &SortFilterProxyModel::rowsRemoved, this, &SortFilterProxyModel::countChanged);
}
int SortFilterProxyModel::getCount() const{
return rowCount();
}
int SortFilterProxyModel::getFilterType () const{
return mFilterType;
}
void SortFilterProxyModel::setFilterType (int filterType) {
if (getFilterType() != filterType) {
mFilterType = filterType;
emit filterTypeChanged(filterType);
invalidate();
}
}
void SortFilterProxyModel::remove(int index, int count){
QSortFilterProxyModel::removeRows(index, count);
}

View file

@ -0,0 +1,49 @@
/*
* 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 SORT_FILTER_PROXY_MODEL_H_
#define SORT_FILTER_PROXY_MODEL_H_
#include <QSortFilterProxyModel>
class SortFilterProxyModel : public QSortFilterProxyModel {
Q_OBJECT
public:
Q_PROPERTY(int count READ getCount NOTIFY countChanged)
Q_PROPERTY(int filterType READ getFilterType WRITE setFilterType NOTIFY filterTypeChanged)
SortFilterProxyModel(QObject * parent = nullptr);
virtual int getCount() const;
virtual int getFilterType () const;
virtual void setFilterType (int filterType);
Q_INVOKABLE void remove(int index, int count = 1);
signals:
void countChanged();
void filterTypeChanged(int filterType);
protected:
int mFilterType;
};
#endif

View file

@ -40,7 +40,7 @@
#include "conferenceInfo/ConferenceInfoModel.hpp"
#include "conferenceInfo/ConferenceInfoListModel.hpp"
#include "conferenceInfo/ConferenceInfoProxyModel.hpp"
#include "conferenceScheduler/ConferenceSchedulerHandler.hpp"
#include "conferenceScheduler/ConferenceScheduler.hpp"
#include "contact/ContactModel.hpp"
#include "contact/VcardModel.hpp"
#include "contacts/ContactsListModel.hpp"

View file

@ -80,7 +80,7 @@ CallModel::CallModel (shared_ptr<linphone::Call> call){
// Update fields and make a search to know to who the call belong
mMagicSearch = CoreManager::getInstance()->getCore()->createMagicSearch();
mSearch = std::make_shared<SearchHandler>(this);
mSearch = std::make_shared<SearchListener>(this);
QObject::connect(mSearch.get(), SIGNAL(searchReceived(std::list<std::shared_ptr<linphone::SearchResult>> )), this, SLOT(searchReceived(std::list<std::shared_ptr<linphone::SearchResult>>)));
mMagicSearch->addListener(mSearch);
@ -161,9 +161,15 @@ ChatRoomModel * CallModel::getChatRoomModel() const{
return nullptr;
}
std::shared_ptr<ConferenceModel> CallModel::getConferenceModel(){
if(mCall->getConference() && !mConferenceModel)
ConferenceModel * CallModel::getConferenceModel(){
return getConferenceSharedModel().get();
}
QSharedPointer<ConferenceModel> CallModel::getConferenceSharedModel(){
if(mCall->getConference() && !mConferenceModel){
mConferenceModel = ConferenceModel::create(mCall->getConference());
emit conferenceModelChanged();
}
return mConferenceModel;
}

View file

@ -22,8 +22,9 @@
#define CALL_MODEL_H_
#include <QObject>
#include <QSharedPointer>
#include <linphone++/linphone.hh>
#include "../search/SearchHandler.hpp"
#include "../search/SearchListener.hpp"
// =============================================================================
class ConferenceModel;
@ -40,6 +41,7 @@ class CallModel : public QObject {
Q_PROPERTY(ContactModel *contactModel READ getContactModel CONSTANT )
Q_PROPERTY(ChatRoomModel * chatRoomModel READ getChatRoomModel CONSTANT)
Q_PROPERTY(ConferenceModel * conferenceModel READ getConferenceModel NOTIFY conferenceModelChanged)
Q_PROPERTY(CallStatus status READ getStatus NOTIFY statusChanged)
Q_PROPERTY(QString callError READ getCallError NOTIFY callErrorChanged)
@ -112,7 +114,8 @@ public:
ContactModel *getContactModel() const;
ChatRoomModel * getChatRoomModel() const;
std::shared_ptr<ConferenceModel> getConferenceModel();
Q_INVOKABLE ConferenceModel* getConferenceModel();
QSharedPointer<ConferenceModel> getConferenceSharedModel();
bool isInConference () const {
return mIsInConference;
@ -174,6 +177,7 @@ public slots:
signals:
void callErrorChanged (const QString &callError);
void isInConferenceChanged (bool status);
void conferenceModelChanged();
void speakerMutedChanged (bool status);
void microMutedChanged (bool status);
void recordingChanged (bool status);
@ -270,9 +274,9 @@ private:
QVariantList mAudioStats;
QVariantList mVideoStats;
std::shared_ptr<SearchHandler> mSearch;
std::shared_ptr<SearchListener> mSearch;
QString mTransferAddress;
std::shared_ptr<ConferenceModel> mConferenceModel;
QSharedPointer<ConferenceModel> mConferenceModel;
};
#endif // CALL_MODEL_H_

View file

@ -183,6 +183,8 @@ void CallsListModel::launchVideoCall (const QString &sipAddress, const QString&
shared_ptr<linphone::CallParams> params = core->createCallParams(nullptr);
params->enableVideo(true);
params->setVideoDirection(linphone::MediaDirection::SendRecv);
params->setConferenceVideoLayout(linphone::ConferenceLayout::Grid);
params->setAccount(core->getDefaultAccount());
CallModel::setRecordFile(params, Utils::coreStringToAppString(address->getUsername()));
CallModel::prepareTransfert(core->inviteAddressWithParams(address, params), prepareTransfertAddress);

View file

@ -31,7 +31,6 @@
class ChatRoomModel;
class CoreHandlers;
class ConferenceModel;
class ConferenceInfoModel;
class CallsListModel : public ProxyListModel {
@ -83,8 +82,6 @@ private:
void removeCall (const std::shared_ptr<linphone::Call> &call);
void removeCallCb (CallModel *callModel);
QList<std::shared_ptr<ConferenceModel>> mConferences;
std::shared_ptr<CoreHandlers> mCoreHandlers;
};

View file

@ -66,6 +66,7 @@ void Camera::resetWindowId() {
QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
QQuickFramebufferObject::Renderer * renderer = NULL;
bool useDefaultWindow = false;
if(mIsPreview){
renderer = (QQuickFramebufferObject::Renderer *)CoreManager::getInstance()->getCore()->getNativePreviewWindowId();
if(renderer)
@ -74,7 +75,6 @@ QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
if(renderer)
CoreManager::getInstance()->getCore()->setNativePreviewWindowId(renderer);
}else{
bool useDefaultWindow = false;
if(mCallModel){
auto call = mCallModel->getCall();
if(call){
@ -92,6 +92,7 @@ QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
renderer = (QQuickFramebufferObject::Renderer *)participantDevice->getNativeVideoWindowId();
if(renderer)
participantDevice->setNativeVideoWindowId(NULL);// Reset
qWarning() << "Trying to create new window ID for " << participantDevice->getName().c_str() << ", addr=" << participantDevice->getAddress()->asString().c_str();
renderer = (QQuickFramebufferObject::Renderer *) participantDevice->createNativeVideoWindowId();
if(renderer)
participantDevice->setNativeVideoWindowId(renderer);

View file

@ -478,7 +478,7 @@ QString ChatRoomModel::getParticipantAddress(){
}else{
auto participants = getParticipants();
if(participants->getCount() > 1)
return participants->getAt(1).objectCast<ParticipantModel>()->getSipAddress();
return participants->getAt<ParticipantModel>(1)->getSipAddress();
else
return "";
}

View file

@ -34,36 +34,14 @@ static inline shared_ptr<linphone::PayloadType> getCodecFromMap (const QVariantM
// -----------------------------------------------------------------------------
AbstractCodecsModel::AbstractCodecsModel (QObject *parent) : QAbstractListModel(parent) {}
int AbstractCodecsModel::rowCount (const QModelIndex &) const {
return mCodecs.count();
}
QHash<int, QByteArray> AbstractCodecsModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$codec";
return roles;
}
QVariant AbstractCodecsModel::data (const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mCodecs.count())
return QVariant();
if (role == Qt::DisplayRole)
return mCodecs[row];
return QVariant();
}
AbstractCodecsModel::AbstractCodecsModel (QObject *parent) : ProxyAbstractListModel<QVariantMap>(parent) {}
// -----------------------------------------------------------------------------
void AbstractCodecsModel::enableCodec (int id, bool status) {
Q_ASSERT(id >= 0 && id < mCodecs.count());
Q_ASSERT(id >= 0 && id < mList.count());
QVariantMap &map = mCodecs[id];
QVariantMap &map = mList[id];
shared_ptr<linphone::PayloadType> codec = getCodecFromMap(map);
if (codec) {
codec->enable(status);
@ -77,9 +55,9 @@ void AbstractCodecsModel::moveCodec (int source, int destination) {
}
void AbstractCodecsModel::setBitrate (int id, int bitrate) {
Q_ASSERT(id >= 0 && id < mCodecs.count());
Q_ASSERT(id >= 0 && id < mList.count());
QVariantMap &map = mCodecs[id];
QVariantMap &map = mList[id];
shared_ptr<linphone::PayloadType> codec = getCodecFromMap(map);
if (codec) {
codec->setNormalBitrate(bitrate);
@ -89,9 +67,9 @@ void AbstractCodecsModel::setBitrate (int id, int bitrate) {
}
void AbstractCodecsModel::setRecvFmtp (int id, const QString &recvFmtp) {
Q_ASSERT(id >= 0 && id < mCodecs.count());
Q_ASSERT(id >= 0 && id < mList.count());
QVariantMap &map = mCodecs[id];
QVariantMap &map = mList[id];
shared_ptr<linphone::PayloadType> codec = getCodecFromMap(map);
if (codec) {
codec->setRecvFmtp(Utils::appStringToCoreString(recvFmtp));
@ -114,7 +92,7 @@ bool AbstractCodecsModel::moveRows (
int limit = sourceRow + count - 1;
{
int nCodecs = mCodecs.count();
int nCodecs = mList.count();
if (
sourceRow < 0 ||
destinationChild < 0 ||
@ -132,16 +110,16 @@ bool AbstractCodecsModel::moveRows (
if (destinationChild > sourceRow) {
--destinationChild;
for (int i = sourceRow; i <= limit; ++i) {
mCodecs.move(sourceRow, destinationChild + i - sourceRow);
mList.move(sourceRow, destinationChild + i - sourceRow);
}
} else {
for (int i = sourceRow; i <= limit; ++i)
mCodecs.move(sourceRow + i - sourceRow, destinationChild + i - sourceRow);
mList.move(sourceRow + i - sourceRow, destinationChild + i - sourceRow);
}
// Update linphone codecs list.
list<shared_ptr<linphone::PayloadType>> codecs;
for (const auto &map : mCodecs) {
for (const auto &map : mList) {
// Do not update downloadable codecs.
shared_ptr<linphone::PayloadType> codec = getCodecFromMap(map);
if (codec)
@ -172,7 +150,7 @@ void AbstractCodecsModel::addCodec (shared_ptr<linphone::PayloadType> &codec) {
map["recvFmtp"] = Utils::coreStringToAppString(codec->getRecvFmtp());
map["__codec"] = QVariant::fromValue(codec);
mCodecs << map;
mList << map;
}
void AbstractCodecsModel::addDownloadableCodec (
@ -188,11 +166,11 @@ void AbstractCodecsModel::addDownloadableCodec (
map["installName"] = installName;
map["mime"] = mime;
mCodecs << map;
mList << map;
}
QVariantMap AbstractCodecsModel::getCodecInfo (const QString &mime) const {
for (const auto &codec : mCodecs)
for (const auto &codec : mList)
if (codec.value("mime") == mime)
return codec;
return QVariantMap();

View file

@ -23,7 +23,7 @@
#include <memory>
#include <QAbstractListModel>
#include "app/proxyModel/ProxyAbstractListModel.hpp"
// =============================================================================
@ -31,19 +31,14 @@ namespace linphone {
class PayloadType;
}
class AbstractCodecsModel : public QAbstractListModel {
Q_OBJECT;
class AbstractCodecsModel : public ProxyAbstractListModel<QVariantMap> {
Q_OBJECT
Q_PROPERTY(QString codecsFolder READ getCodecsFolder CONSTANT);
Q_PROPERTY(QString codecsFolder READ getCodecsFolder CONSTANT)
public:
AbstractCodecsModel (QObject *parent = Q_NULLPTR);
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;
Q_INVOKABLE void enableCodec (int id, bool status);
Q_INVOKABLE void moveCodec (int source, int destination);
@ -74,8 +69,6 @@ protected:
virtual void updateCodecs (std::list<std::shared_ptr<linphone::PayloadType>> &codecs) = 0;
static QString getCodecsFolder ();
QList<QVariantMap> mCodecs;
};
Q_DECLARE_METATYPE(std::shared_ptr<linphone::PayloadType>);

View file

@ -139,7 +139,7 @@ void VideoCodecsModel::updateCodecs (list<shared_ptr<linphone::PayloadType>> &co
}
void VideoCodecsModel::load () {
mCodecs.clear();
resetData();
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();

View file

@ -54,7 +54,7 @@ int ConferenceHelperModel::ConferenceAddModel::rowCount (const QModelIndex &) co
QHash<int, QByteArray> ConferenceHelperModel::ConferenceAddModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$sipAddress";
roles[Qt::DisplayRole] = "$modelData";
return roles;
}

View file

@ -52,7 +52,7 @@ ConferenceHelperModel::ConferenceHelperModel (QObject *parent) : QSortFilterProx
QHash<int, QByteArray> ConferenceHelperModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$sipAddress";
roles[Qt::DisplayRole] = "$modelData";
return roles;
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2021 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 "ConferenceListener.hpp"
#include <QQmlApplicationEngine>
#include <QDesktopServices>
#include <QImageReader>
#include <QMessageBox>
#include "app/App.hpp"
#include "app/paths/Paths.hpp"
// =============================================================================
ConferenceListener::ConferenceListener () : QObject(nullptr) {
}
ConferenceListener::~ConferenceListener(){
}
//-----------------------------------------------------------------------------------------------------------------------
// LINPHONE LISTENERS
//-----------------------------------------------------------------------------------------------------------------------
void ConferenceListener::onParticipantAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant){
qWarning() << "onParticipantAdded";
emit participantAdded(participant);
}
void ConferenceListener::onParticipantRemoved(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant){
qWarning() << "onParticipantRemoved";
emit participantRemoved(participant);
}
void ConferenceListener::onParticipantDeviceAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "onParticipantDeviceAdded";
qWarning() << "Me devices : " << conference->getMe()->getDevices().size();
emit participantDeviceAdded(participantDevice);
}
void ConferenceListener::onParticipantDeviceRemoved(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "onParticipantDeviceRemoved";
qWarning() << "Me devices : " << conference->getMe()->getDevices().size();
emit participantDeviceRemoved(participantDevice);
}
void ConferenceListener::onParticipantAdminStatusChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant){
qWarning() << "onParticipantAdminStatusChanged";
}
void ConferenceListener::onParticipantDeviceLeft(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "onParticipantDeviceLeft";
qWarning() << "Me devices : " << conference->getMe()->getDevices().size();
emit participantDeviceLeft(participantDevice);
}
void ConferenceListener::onParticipantDeviceJoined(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "onParticipantDeviceJoined";
qWarning() << "Me devices : " << conference->getMe()->getDevices().size();
emit participantDeviceJoined(participantDevice);
}
void ConferenceListener::onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "onParticipantDeviceMediaAvailabilityChanged";
qWarning() << "ConferenceListener::onParticipantDeviceMediaAvailabilityChanged: " << (int)participantDevice->getStreamAvailability(linphone::StreamType::Video) << ". Me devices : " << conference->getMe()->getDevices().size();
emit participantDeviceMediaAvailabilityChanged(participantDevice);
}
void ConferenceListener::onStateChanged(const std::shared_ptr<linphone::Conference> & conference, linphone::Conference::State newState){
qWarning() << "onStateChanged";
emit conferenceStateChanged(newState);
}
void ConferenceListener::onSubjectChanged(const std::shared_ptr<linphone::Conference> & conference, const std::string & subject){
qWarning() << "onSubjectChanged";
emit subjectChanged(subject);
}
void ConferenceListener::onAudioDeviceChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::AudioDevice> & audioDevice){
qWarning() << "onAudioDeviceChanged is not yet implemented.";
}
//-----------------------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2021 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 CONFERENCE_LISTENER_H_
#define CONFERENCE_LISTENER_H_
#include <linphone++/linphone.hh>
// =============================================================================
#include <QObject>
#include <QDateTime>
#include <QString>
class ConferenceListener : public QObject, public linphone::ConferenceListener{
Q_OBJECT
public:
ConferenceListener();
virtual ~ConferenceListener();
// LINPHONE LISTENERS
virtual void onParticipantAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant) override;
virtual void onParticipantRemoved(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant) override;
virtual void onParticipantDeviceAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice) override;
virtual void onParticipantDeviceRemoved(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice) override;
virtual void onParticipantAdminStatusChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant) override;
virtual void onParticipantDeviceLeft(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & device) override;
virtual void onParticipantDeviceJoined(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & device) override;
virtual void onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & device) override;
virtual void onStateChanged(const std::shared_ptr<linphone::Conference> & conference, linphone::Conference::State newState) override;
virtual void onSubjectChanged(const std::shared_ptr<linphone::Conference> & conference, const std::string & subject) override;
virtual void onAudioDeviceChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::AudioDevice> & audioDevice) override;
//---------------------------------------------------------------------------
signals:
void participantAdded(const std::shared_ptr<const linphone::Participant> & participant);
void participantRemoved(const std::shared_ptr<const linphone::Participant> & participant);
void participantDeviceAdded(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void participantDeviceRemoved(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void participantDeviceLeft(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void participantDeviceJoined(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void participantDeviceMediaAvailabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void conferenceStateChanged(linphone::Conference::State newState);
void subjectChanged(const std::string & subject);
};
#endif

View file

@ -19,6 +19,7 @@
*/
#include "ConferenceModel.hpp"
#include "ConferenceListener.hpp"
#include <QQmlApplicationEngine>
#include <QDesktopServices>
@ -35,71 +36,88 @@
#include "utils/Constants.hpp"
#include "components/Components.hpp"
void ConferenceModel::connectTo(ConferenceListener * listener){
connect(listener, &ConferenceListener::participantAdded, this, &ConferenceModel::onParticipantAdded);
connect(listener, &ConferenceListener::participantRemoved, this, &ConferenceModel::onParticipantRemoved);
connect(listener, &ConferenceListener::participantDeviceAdded, this, &ConferenceModel::onParticipantDeviceAdded);
connect(listener, &ConferenceListener::participantDeviceRemoved, this, &ConferenceModel::onParticipantDeviceRemoved);
connect(listener, &ConferenceListener::participantDeviceLeft, this, &ConferenceModel::onParticipantDeviceLeft);
connect(listener, &ConferenceListener::participantDeviceJoined, this, &ConferenceModel::onParticipantDeviceJoined);
connect(listener, &ConferenceListener::participantDeviceMediaAvailabilityChanged, this, &ConferenceModel::onParticipantDeviceMediaAvailabilityChanged);
connect(listener, &ConferenceListener::conferenceStateChanged, this, &ConferenceModel::onConferenceStateChanged);
connect(listener, &ConferenceListener::subjectChanged, this, &ConferenceModel::onSubjectChanged);
}
// =============================================================================
std::shared_ptr<ConferenceModel> ConferenceModel::create(std::shared_ptr<linphone::Conference> conference, QObject *parent){
std::shared_ptr<ConferenceModel> model = std::make_shared<ConferenceModel>(conference, parent);
if(model){
model->mSelf = model;
conference->addListener(model);
return model;
}
return nullptr;
QSharedPointer<ConferenceModel> ConferenceModel::create(std::shared_ptr<linphone::Conference> conference, QObject *parent){
return QSharedPointer<ConferenceModel>::create(conference, parent);
}
ConferenceModel::ConferenceModel (std::shared_ptr<linphone::Conference> conference, QObject *parent) : QObject(parent) {
App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE
mConference = conference;
mConferenceListener = std::make_shared<ConferenceListener>();
connectTo(mConferenceListener.get());
mConference->addListener(mConferenceListener);
}
ConferenceModel::~ConferenceModel(){
//mChatRoomModel->getChatRoom()->removeListener(mChatRoomModel);
mConference->removeListener(mConferenceListener);
}
std::shared_ptr<linphone::Conference> ConferenceModel::getConference()const{
return mConference;
}
QString ConferenceModel::getSubject() const{
return QString::fromStdString(mConference->getSubject());
}
QDateTime ConferenceModel::getStartDate() const{
return QDateTime::fromSecsSinceEpoch(mConference->getStartTime());
}
qint64 ConferenceModel::getElapsedSeconds() const {
return getStartDate().secsTo(QDateTime::currentDateTime());
}
//-----------------------------------------------------------------------------------------------------------------------
// LINPHONE LISTENERS
//-----------------------------------------------------------------------------------------------------------------------
void ConferenceModel::onParticipantAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant){
qWarning() << "onParticipantAdded is not yet implemented.";
qWarning() << "Me devices : " << conference->getMe()->getDevices().size();
void ConferenceModel::onParticipantAdded(const std::shared_ptr<const linphone::Participant> & participant){
qWarning() << "Me devices : " << mConference->getMe()->getDevices().size();
emit participantAdded(participant);
}
void ConferenceModel::onParticipantRemoved(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant){
qWarning() << "onParticipantRemoved is not yet implemented.";
qWarning() << "Me devices : " << conference->getMe()->getDevices().size();
void ConferenceModel::onParticipantRemoved(const std::shared_ptr<const linphone::Participant> & participant){
qWarning() << "Me devices : " << mConference->getMe()->getDevices().size();
emit participantRemoved(participant);
}
void ConferenceModel::onParticipantDeviceAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "Me devices : " << conference->getMe()->getDevices().size();
void ConferenceModel::onParticipantDeviceAdded(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "Me devices : " << mConference->getMe()->getDevices().size();
emit participantDeviceAdded(participantDevice);
}
void ConferenceModel::onParticipantDeviceRemoved(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "Me devices : " << conference->getMe()->getDevices().size();
void ConferenceModel::onParticipantDeviceRemoved(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "Me devices : " << mConference->getMe()->getDevices().size();
emit participantDeviceRemoved(participantDevice);
}
void ConferenceModel::onParticipantAdminStatusChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant){
}
void ConferenceModel::onParticipantDeviceLeft(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "Me devices : " << conference->getMe()->getDevices().size();
void ConferenceModel::onParticipantDeviceLeft(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "Me devices : " << mConference->getMe()->getDevices().size();
emit participantDeviceLeft(participantDevice);
}
void ConferenceModel::onParticipantDeviceJoined(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "Me devices : " << conference->getMe()->getDevices().size();
void ConferenceModel::onParticipantDeviceJoined(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "Me devices : " << mConference->getMe()->getDevices().size();
emit participantDeviceJoined(participantDevice);
}
void ConferenceModel::onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "ConferenceModel::onParticipantDeviceMediaAvailabilityChanged: " << (int)participantDevice->getStreamAvailability(linphone::StreamType::Video) << ". Me devices : " << conference->getMe()->getDevices().size();
void ConferenceModel::onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "ConferenceModel::onParticipantDeviceMediaAvailabilityChanged: " << (int)participantDevice->getStreamAvailability(linphone::StreamType::Video) << ". Me devices : " << mConference->getMe()->getDevices().size();
emit participantDeviceMediaAvailabilityChanged(participantDevice);
}
void ConferenceModel::onStateChanged(const std::shared_ptr<linphone::Conference> & conference, linphone::Conference::State newState){
void ConferenceModel::onConferenceStateChanged(linphone::Conference::State newState){
emit conferenceStateChanged(newState);
}
void ConferenceModel::onSubjectChanged(const std::shared_ptr<linphone::Conference> & conference, const std::string & subject){
qWarning() << "onSubjectChanged is not yet implemented.";
}
void ConferenceModel::onAudioDeviceChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::AudioDevice> & audioDevice){
qWarning() << "onAudioDeviceChanged is not yet implemented.";
void ConferenceModel::onSubjectChanged(const std::string& string){
emit subjectChanged();
}

View file

@ -28,41 +28,53 @@
#include <QDateTime>
#include <QString>
class ConferenceModel : public QObject, public linphone::ConferenceListener{
class ConferenceListener;
class ConferenceModel : public QObject{
Q_OBJECT
public:
static std::shared_ptr<ConferenceModel> create(std::shared_ptr<linphone::Conference> chatRoom, QObject *parent = Q_NULLPTR);
Q_PROPERTY(QString subject READ getSubject NOTIFY subjectChanged)
Q_PROPERTY(QDateTime startDate READ getStartDate CONSTANT)
static QSharedPointer<ConferenceModel> create(std::shared_ptr<linphone::Conference> chatRoom, QObject *parent = Q_NULLPTR);
ConferenceModel(std::shared_ptr<linphone::Conference> content, QObject *parent = Q_NULLPTR);
virtual ~ConferenceModel();
std::shared_ptr<linphone::Conference> getConference()const;
QString getSubject() const;
QDateTime getStartDate() const;
Q_INVOKABLE qint64 getElapsedSeconds() const;
// LINPHONE LISTENERS
virtual void onParticipantAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant) override;
virtual void onParticipantRemoved(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant) override;
virtual void onParticipantDeviceAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice) override;
virtual void onParticipantDeviceRemoved(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice) override;
virtual void onParticipantAdminStatusChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant) override;
virtual void onParticipantDeviceLeft(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & device) override;
virtual void onParticipantDeviceJoined(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & device) override;
virtual void onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & device) override;
virtual void onStateChanged(const std::shared_ptr<linphone::Conference> & conference, linphone::Conference::State newState) override;
virtual void onSubjectChanged(const std::shared_ptr<linphone::Conference> & conference, const std::string & subject) override;
virtual void onAudioDeviceChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::AudioDevice> & audioDevice) override;
virtual void onParticipantAdded(const std::shared_ptr<const linphone::Participant> & participant);
virtual void onParticipantRemoved(const std::shared_ptr<const linphone::Participant> & participant);
virtual void onParticipantDeviceAdded(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
virtual void onParticipantDeviceRemoved(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
virtual void onParticipantDeviceLeft(const std::shared_ptr<const linphone::ParticipantDevice> & device);
virtual void onParticipantDeviceJoined(const std::shared_ptr<const linphone::ParticipantDevice> & device);
virtual void onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & device);
virtual void onConferenceStateChanged(linphone::Conference::State newState);
virtual void onSubjectChanged(const std::string& subject);
//---------------------------------------------------------------------------
signals:
void participantAdded(const std::shared_ptr<const linphone::Participant> & participant);
void participantRemoved(const std::shared_ptr<const linphone::Participant> & participant);
void participantDeviceAdded(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void participantDeviceRemoved(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void participantDeviceLeft(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void participantDeviceJoined(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void participantDeviceMediaAvailabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void conferenceStateChanged(linphone::Conference::State newState);
void subjectChanged();
private:
void connectTo(ConferenceListener * listener);
std::shared_ptr<linphone::Conference> mConference;
std::weak_ptr<ConferenceModel> mSelf;
std::shared_ptr<ConferenceListener> mConferenceListener;
};
Q_DECLARE_METATYPE(std::shared_ptr<ConferenceModel>)
Q_DECLARE_METATYPE(QSharedPointer<ConferenceModel>)
#endif

View file

@ -37,13 +37,7 @@
using namespace std;
ConferenceProxyModel::ConferenceProxyModel (QObject *parent) : QSortFilterProxyModel(parent) {
QObject::connect(this, &ConferenceProxyModel::rowsRemoved, [this] { // Warning : called before model remove its items
emit countChanged(rowCount());
});
QObject::connect(this, &ConferenceProxyModel::rowsInserted, [this] {
emit countChanged(rowCount());
});
ConferenceProxyModel::ConferenceProxyModel (QObject *parent) : SortFilterProxyModel(parent) {
setSourceModel(CoreManager::getInstance()->getCallsListModel());
emit conferenceChanged();

View file

@ -21,16 +21,14 @@
#ifndef CONFERENCE_PROXY_MODEL_H_
#define CONFERENCE_PROXY_MODEL_H_
#include <QSortFilterProxyModel>
#include "app/proxyModel/SortFilterProxyModel.hpp"
// =============================================================================
class CallModel;
class ConferenceProxyModel : public QSortFilterProxyModel {
Q_OBJECT;
Q_PROPERTY(int count READ getCount NOTIFY countChanged);
class ConferenceProxyModel : public SortFilterProxyModel {
Q_OBJECT
Q_PROPERTY(bool microMuted READ getMicroMuted WRITE setMicroMuted NOTIFY microMutedChanged);
Q_PROPERTY(float microVu READ getMicroVu CONSTANT);
@ -53,17 +51,11 @@ protected:
Q_INVOKABLE void leave ();
signals:
void countChanged (int count);
void microMutedChanged (bool status);
void recordingChanged (bool status);
void conferenceChanged ();
private:
int getCount () const {
return rowCount();
}
bool getMicroMuted () const;
void setMicroMuted (bool status);
float getMicroVu () const;

View file

@ -38,14 +38,14 @@
ConferenceInfoListModel::ConferenceInfoListModel (QObject *parent) : ProxyListModel(parent) {
//auto conferenceInfos = CoreManager::getInstance()->getCore()->getConferenceInformationList();
//for(auto conferenceInfo : conferenceInfos){
// auto conferenceInfoModel = ConferenceInfoModel::create( conferenceInfo );
// mList << conferenceInfoModel;
//auto conferenceInfoModel = ConferenceInfoModel::create( conferenceInfo );
//mList << conferenceInfoModel;
//mMappedList[conferenceInfoModel->getDateTime().date()].push_back(conferenceInfoModel.get());
// }
//}
}
/*
ConferenceInfoModel* ConferenceInfoListModel::getAt(const int& index) const {
return ProxyListModel::getAt(index).objectCast<ConferenceInfoModel>().get();
}
*/
// -----------------------------------------------------------------------------

View file

@ -35,7 +35,7 @@ class ConferenceInfoListModel : public ProxyListModel {
public:
ConferenceInfoListModel (QObject *parent = Q_NULLPTR);
ConferenceInfoModel* getAt(const int& index) const;
// ConferenceInfoModel* getAt(const int& index) const;
};
Q_DECLARE_METATYPE(QList<ConferenceInfoModel*>*)
#endif

View file

@ -35,10 +35,11 @@
#include "ConferenceInfoProxyModel.hpp"
#include "ConferenceInfoListModel.hpp"
#include "ConferenceInfoModel.hpp"
#include "ConferenceInfoProxyListModel.hpp"
// =============================================================================
ConferenceInfoMapModel::ConferenceInfoMapModel (QObject *parent) : QAbstractListModel(parent) {
ConferenceInfoMapModel::ConferenceInfoMapModel (QObject *parent) : ProxyAbstractMapModel<QDate,SortFilterAbstractProxyModel<ConferenceInfoListModel>*>(parent) {
auto conferenceInfos = CoreManager::getInstance()->getCore()->getConferenceInformationList();
auto me = CoreManager::getInstance()->getCore()->getDefaultAccount()->getParams()->getIdentityAddress();
for(auto conferenceInfo : conferenceInfos){
@ -51,43 +52,16 @@ ConferenceInfoMapModel::ConferenceInfoMapModel (QObject *parent) : QAbstractList
if(haveMe){
auto conferenceInfoModel = ConferenceInfoModel::create( conferenceInfo );
QDate t = conferenceInfoModel->getDateTime().date();
if( !mMappedList.contains(t))
mMappedList[t] = new ConferenceInfoProxyModel(new ConferenceInfoListModel(), this);
if( !mMappedList.contains(t)){
//auto proxy = new SortFilterAbstractProxyModel<ConferenceInfoListModel>(new ConferenceInfoListModel(), this);
auto proxy = new ConferenceInfoProxyListModel(this);
connect(this, &ConferenceInfoMapModel::filterTypeChanged, proxy, &ConferenceInfoProxyListModel::setFilterType);
mMappedList[t] = proxy;
}
//mMappedList[t] = new ConferenceInfoProxyModel(new ConferenceInfoListModel(), this);
mMappedList[t]->add(conferenceInfoModel);
}
}
}
int ConferenceInfoMapModel::rowCount (const QModelIndex &) const {
return mMappedList.size();
}
QHash<int, QByteArray> ConferenceInfoMapModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$modelData";
roles[Qt::DisplayRole + 1] = "date";
return roles;
}
QVariant ConferenceInfoMapModel::data (const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mMappedList.size())
return QVariant();
auto it = mMappedList.begin() + row;
if (role == Qt::DisplayRole)
return QVariant::fromValue(*it);
else if( role == Qt::DisplayRole+1)
return QVariant::fromValue(it.key());
return QVariant();
}
// -----------------------------------------------------------------------------
void ConferenceInfoMapModel::setConferenceInfoFilter (int filterMode){
for(auto list : mMappedList){
list->setConferenceInfoFilter(filterMode);
}
}
// -----------------------------------------------------------------------------

View file

@ -22,29 +22,23 @@
#define _CONFERENCE_INFO_MAP_MODEL_H_
#include <linphone++/linphone.hh>
#include <QAbstractListModel>
#include <QDate>
#include "app/proxyModel/ProxyAbstractMapModel.hpp"
#include "app/proxyModel/SortFilterAbstractProxyModel.hpp"
class ConferenceInfoListModel;
// =============================================================================
class ConferenceInfoProxyModel;
class ConferenceInfoMapModel : public QAbstractListModel {
Q_OBJECT
class ConferenceInfoMapModel : public ProxyAbstractMapModel<QDate,SortFilterAbstractProxyModel<ConferenceInfoListModel>*> {
Q_OBJECT
public:
ConferenceInfoMapModel (QObject *parent = Q_NULLPTR);
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;
Q_INVOKABLE void setConferenceInfoFilter (int filterMode);
private:
QMap<QDate, ConferenceInfoProxyModel*> mMappedList;
ConferenceInfoMapModel (QObject *parent = Q_NULLPTR);
signals:
void filterTypeChanged(int filterType);
};
Q_DECLARE_METATYPE(ConferenceInfoMapModel*)
#endif

View file

@ -45,7 +45,7 @@
#include "components/contact/ContactModel.hpp"
#include "components/contact/VcardModel.hpp"
#include "components/contacts/ContactsListModel.hpp"
#include "components/conferenceScheduler/ConferenceSchedulerHandler.hpp"
#include "components/conferenceScheduler/ConferenceScheduler.hpp"
#include "components/core/CoreHandlers.hpp"
#include "components/core/CoreManager.hpp"
#include "components/notifier/Notifier.hpp"
@ -74,13 +74,7 @@ using namespace std;
// -----------------------------------------------------------------------------
QSharedPointer<ConferenceInfoModel> ConferenceInfoModel::create(std::shared_ptr<linphone::ConferenceInfo> conferenceInfo){
QSharedPointer<ConferenceInfoModel> model = QSharedPointer<ConferenceInfoModel>::create(conferenceInfo);
if(model){
model->mSelf = model;
//chatRoom->addListener(model);
return model;
}else
return nullptr;
return QSharedPointer<ConferenceInfoModel>::create(conferenceInfo);
}
ConferenceInfoModel::ConferenceInfoModel (QObject * parent) : QObject(parent){
@ -157,6 +151,7 @@ bool ConferenceInfoModel::isScheduled() const{
void ConferenceInfoModel::setDateTime(const QDateTime& dateTime){
mConferenceInfo->setDateTime(dateTime.toMSecsSinceEpoch() / 1000);
qWarning() << "Set DateTime: " << mConferenceInfo->getDateTime() << " from " << dateTime.toMSecsSinceEpoch() / 1000;
emit dateTimeChanged();
}
@ -201,10 +196,9 @@ void ConferenceInfoModel::createConference(const int& securityLevel, const int&
qInfo() << "Conference creation of " << getSubject() << " at " << securityLevel << " security, organized by " << getOrganizer();// and with " << conferenceInfo->getConferenceInfo()->getParticipants().size();
if( true || isScheduled()){
mConferenceSchedulerHandler = ConferenceSchedulerHandler::create(this);
connect(mConferenceSchedulerHandler.get(), &ConferenceSchedulerHandler::invitationsSent, this, &ConferenceInfoModel::onInvitationsSent);
mConferenceSchedulerHandler->getConferenceScheduler()->setInfo(mConferenceInfo);
mConferenceScheduler = ConferenceScheduler::create();
connect(mConferenceScheduler.get(), &ConferenceScheduler::invitationsSent, this, &ConferenceInfoModel::onInvitationsSent);
mConferenceScheduler->getConferenceScheduler()->setInfo(mConferenceInfo);
}else{
auto conferenceParameters = core->createConferenceParams(nullptr);
conferenceParameters->enableAudio(true);
@ -233,6 +227,5 @@ void ConferenceInfoModel::createConference(const int& securityLevel, const int&
void ConferenceInfoModel::onInvitationsSent(const std::list<std::shared_ptr<linphone::Address>> & failedInvitations) {
mConferenceSchedulerHandler->getConferenceScheduler()->removeListener(mConferenceSchedulerHandler);
emit invitationsSent();
}

View file

@ -27,7 +27,7 @@
#include <QSharedPointer>
class ParticipantListModel;
class ConferenceSchedulerHandler;
class ConferenceScheduler;
class ConferenceInfoModel : public QObject {
Q_OBJECT
@ -97,9 +97,8 @@ signals:
private:
std::shared_ptr<linphone::ConferenceInfo> mConferenceInfo;
std::shared_ptr<ConferenceSchedulerHandler> mConferenceSchedulerHandler = nullptr;
QSharedPointer<ConferenceScheduler> mConferenceScheduler= nullptr;
QWeakPointer<ConferenceInfoModel> mSelf; // For Linphone listener
bool mIsScheduled = true;
};

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2021 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 "ConferenceInfoProxyListModel.hpp"
#include "components/call/CallModel.hpp"
#include "components/core/CoreManager.hpp"
#include "ConferenceInfoListModel.hpp"
#include "ConferenceInfoMapModel.hpp"
// =============================================================================
using namespace std;
//---------------------------------------------------------------------------------------------
ConferenceInfoProxyListModel::ConferenceInfoProxyListModel (QObject *parent) : SortFilterAbstractProxyModel<ConferenceInfoListModel>(new ConferenceInfoListModel(parent), parent) {
//setFilterType(0);
//connect(this, &ConferenceInfoProxyListModel::filterTypeChanged, qobject_cast<ConferenceInfoListModel*>(sourceModel()), &ConferenceInfoListModel::filterTypeChanged);
}
bool ConferenceInfoProxyListModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const {
auto listModel = qobject_cast<ConferenceInfoListModel*>(sourceModel());
if(listModel){
QModelIndex index = listModel->index(sourceRow, 0, QModelIndex());
const ConferenceInfoModel* ics = sourceModel()->data(index).value<ConferenceInfoModel*>();
if(ics){
QDateTime currentDateTime = QDateTime::currentDateTime();
if( mFilterType == 0){
return ics->getEndDateTime() < currentDateTime;
}else if( mFilterType == 1){
return ics->getDateTime() >= currentDateTime;
}
}
}
return true;
/*
bool show = false;
QModelIndex index = sourceModel()->index(sourceRow, 0, QModelIndex());
const ConferenceInfoListModel* ics = sourceModel()->data(index).value<ConferenceInfoListModel*>();
if( mEntryTypeFilter == ConferenceType::Ended && ics->eventModel.value<ChatCallModel*>() != nullptr)
show = true;
else if( mEntryTypeFilter == ChatRoomModel::EntryType::MessageEntry && eventModel.value<ChatMessageModel*>() != nullptr)
show = true;
else if( mEntryTypeFilter == ChatRoomModel::EntryType::NoticeEntry && eventModel.value<ChatNoticeModel*>() != nullptr)
show = true;
}
if( show && mFilterText != ""){
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
auto eventModel = sourceModel()->data(index);
ChatMessageModel * chatModel = eventModel.value<ChatMessageModel*>();
if( chatModel){
QRegularExpression search(QRegularExpression::escape(mFilterText), QRegularExpression::CaseInsensitiveOption | QRegularExpression::UseUnicodePropertiesOption);
show = chatModel->mContent.contains(search);
}
}
return show;*/
}
bool ConferenceInfoProxyListModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
return true;
/*
const ConferenceInfoListModel* deviceA = sourceModel()->data(left).value<ConferenceInfoListModel*>();
const ConferenceInfoListModel* deviceB = sourceModel()->data(right).value<ConferenceInfoListModel*>();
return deviceA->getAt<ConferenceInfoModel>(0)->getDateTime() < deviceB->getAt<ConferenceInfoModel>(0)->getDateTime();
*/
}
/*
QVariant ConferenceInfoProxyModel::getAt(int row){
QModelIndex sourceIndex = mapToSource(this->index(row, 0));
return sourceModel()->data(sourceIndex);
}
void ConferenceInfoProxyModel::add(QSharedPointer<ConferenceInfoModel> conferenceInfoModel){
qobject_cast<ConferenceInfoListModel*>(sourceModel())->add(conferenceInfoModel);
}*/

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Belledonne Communications SARL.
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
@ -18,33 +18,31 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CONFERENCE_INFO_MAP_MODEL_H_
#define _CONFERENCE_INFO_MAP_MODEL_H_
#ifndef CONFERENCE_INFO_PROXY_LIST_MODEL_H_
#define CONFERENCE_INFO_PROXY_LIST_MODEL_H_
#include <QSortFilterProxyModel>
#include <QSharedPointer>
#include "ConferenceInfoModel.hpp"
#include "app/proxyModel/SortFilterAbstractProxyModel.hpp"
#include <linphone++/linphone.hh>
#include <QAbstractListModel>
#include <QDate>
// =============================================================================
class ConferenceInfoProxyModel;
class QWindow;
class ConferenceInfoListModel;
class ConferenceInfoMapModel : public QAbstractListModel {
Q_OBJECT
class ConferenceInfoProxyListModel : public SortFilterAbstractProxyModel<ConferenceInfoListModel> {
Q_OBJECT
public:
ConferenceInfoMapModel (QObject *parent = Q_NULLPTR);
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;
Q_INVOKABLE void setConferenceInfoFilter (int filterMode);
private:
QMap<QDate, ConferenceInfoProxyModel*> mMappedList;
ConferenceInfoProxyListModel (QObject *parent = Q_NULLPTR);
protected:
bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
bool lessThan (const QModelIndex &left, const QModelIndex &right) const override;
};
Q_DECLARE_METATYPE(ConferenceInfoMapModel*)
#endif

View file

@ -18,43 +18,39 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ConferenceInfoProxyModel.hpp"
#include "components/call/CallModel.hpp"
#include "components/core/CoreManager.hpp"
#include "ConferenceInfoListModel.hpp"
#include "ConferenceInfoMapModel.hpp"
#include "ConferenceInfoProxyModel.hpp"
#include "ConferenceInfoProxyListModel.hpp"
// =============================================================================
using namespace std;
ConferenceInfoProxyModel::ConferenceInfoProxyModel (QObject *parent) : QSortFilterProxyModel(parent) {
mEntryTypeFilter = ConferenceType::Scheduled;
setSourceModel(new ConferenceInfoMapModel());
sort(0, Qt::DescendingOrder);
}
//---------------------------------------------------------------------------------------------
ConferenceInfoProxyModel::ConferenceInfoProxyModel (ConferenceInfoListModel * list, QObject *parent) : QSortFilterProxyModel(parent) {
mEntryTypeFilter = ConferenceType::Scheduled;
setSourceModel(list);
sort(0, Qt::DescendingOrder);
}
int ConferenceInfoProxyModel::getConferenceInfoFilter () {
return mEntryTypeFilter;
}
void ConferenceInfoProxyModel::setConferenceInfoFilter (int filterMode) {
if (getConferenceInfoFilter() != filterMode) {
mEntryTypeFilter = filterMode;
invalidate();
emit conferenceInfoFilterChanged(filterMode);
}
ConferenceInfoProxyModel::ConferenceInfoProxyModel (QObject *parent) : SortFilterAbstractProxyModel<ConferenceInfoMapModel>(new ConferenceInfoMapModel(parent), parent) {
setFilterType((int)Scheduled);
connect(this, &ConferenceInfoProxyModel::filterTypeChanged, qobject_cast<ConferenceInfoMapModel*>(sourceModel()), &ConferenceInfoMapModel::filterTypeChanged);
}
bool ConferenceInfoProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const {
return true;
QModelIndex index = sourceModel()->index(sourceRow, 0, QModelIndex());
const ConferenceInfoMapModel* ics = sourceModel()->data(index).value<ConferenceInfoMapModel*>();
if(ics){
int r = ics->rowCount();
return r > 0;
}
const ConferenceInfoProxyListModel* listModel = sourceModel()->data(index).value<ConferenceInfoProxyListModel*>();
if(listModel){
int r = listModel->rowCount();
return r > 0;
}
return false;
/*
bool show = false;
QModelIndex index = sourceModel()->index(sourceRow, 0, QModelIndex());
@ -81,12 +77,15 @@ bool ConferenceInfoProxyModel::filterAcceptsRow (int sourceRow, const QModelInde
}
bool ConferenceInfoProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
return true;
/*
const ConferenceInfoListModel* deviceA = sourceModel()->data(left).value<ConferenceInfoListModel*>();
const ConferenceInfoListModel* deviceB = sourceModel()->data(right).value<ConferenceInfoListModel*>();
return deviceA->getAt(0)->getDateTime() < deviceB->getAt(0)->getDateTime();
return deviceA->getAt<ConferenceInfoModel>(0)->getDateTime() < deviceB->getAt<ConferenceInfoModel>(0)->getDateTime();
*/
}
/*
QVariant ConferenceInfoProxyModel::getAt(int row){
QModelIndex sourceIndex = mapToSource(this->index(row, 0));
return sourceModel()->data(sourceIndex);
@ -94,4 +93,4 @@ QVariant ConferenceInfoProxyModel::getAt(int row){
void ConferenceInfoProxyModel::add(QSharedPointer<ConferenceInfoModel> conferenceInfoModel){
qobject_cast<ConferenceInfoListModel*>(sourceModel())->add(conferenceInfoModel);
}
}*/

View file

@ -25,40 +25,29 @@
#include <QSharedPointer>
#include "ConferenceInfoModel.hpp"
#include "app/proxyModel/SortFilterAbstractProxyModel.hpp"
// =============================================================================
class QWindow;
class ConferenceInfoListModel;
class ConferenceInfoMapModel;
class ConferenceInfoProxyModel : public QSortFilterProxyModel {
class ConferenceInfoProxyModel : public SortFilterAbstractProxyModel<ConferenceInfoMapModel> {
class ChatRoomModelFilter;
Q_OBJECT
public:
Q_PROPERTY(int conferenceInfoFilter READ getConferenceInfoFilter WRITE setConferenceInfoFilter NOTIFY conferenceInfoFilterChanged)
enum ConferenceType {
Ended,
Scheduled,
Invitations
};
Q_ENUM(ConferenceType)
ConferenceInfoProxyModel (QObject *parent = Q_NULLPTR);
ConferenceInfoProxyModel (ConferenceInfoListModel * list, QObject *parent = Q_NULLPTR);
int getConferenceInfoFilter ();
Q_INVOKABLE void setConferenceInfoFilter (int filterMode);
Q_INVOKABLE QVariant getAt(int row);
void add(QSharedPointer<ConferenceInfoModel> conferenceInfoModel);
signals:
void conferenceInfoFilterChanged(int);
protected:
bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
bool lessThan (const QModelIndex &left, const QModelIndex &right) const override;
@ -68,7 +57,7 @@ private:
ConferenceInfoModel *getConferenceInfoModel() const;
void setConferenceInfoModel (ConferenceInfoModel *conferenceInfoModel);
int mEntryTypeFilter;
QSharedPointer<ConferenceInfoModel> mConferenceInfoModel;
};

View file

@ -18,38 +18,42 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ConferenceSchedulerHandler.hpp"
#include "ConferenceScheduler.hpp"
#include "ConferenceSchedulerListener.hpp"
#include <QQmlApplicationEngine>
#include "app/App.hpp"
#include "components/core/CoreManager.hpp"
// =============================================================================
std::shared_ptr<ConferenceSchedulerHandler> ConferenceSchedulerHandler::create( QObject *parent){
std::shared_ptr<ConferenceSchedulerHandler> model = std::make_shared<ConferenceSchedulerHandler>(parent);
if(model){
model->mSelf = model;
model->mConferenceScheduler->addListener(model);
return model;
}
return nullptr;
void ConferenceScheduler::connectTo(ConferenceSchedulerListener * listener){
connect(listener, &ConferenceSchedulerListener::stateChanged, this, &ConferenceScheduler::onStateChanged);
connect(listener, &ConferenceSchedulerListener::invitationsSent, this, &ConferenceScheduler::onInvitationsSent);
}
ConferenceSchedulerHandler::ConferenceSchedulerHandler (QObject * parent) : QObject(parent){
// =============================================================================
QSharedPointer<ConferenceScheduler> ConferenceScheduler::create( QObject *parent){
return QSharedPointer<ConferenceScheduler>::create(parent);
}
ConferenceScheduler::ConferenceScheduler (QObject * parent) : QObject(parent){
App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE
mConferenceScheduler = CoreManager::getInstance()->getCore()->createConferenceScheduler();
mConferenceSchedulerListener = std::make_shared<ConferenceSchedulerListener>();
connectTo(mConferenceSchedulerListener.get());
mConferenceScheduler->addListener(mConferenceSchedulerListener);
}
ConferenceSchedulerHandler::~ConferenceSchedulerHandler () {
ConferenceScheduler::~ConferenceScheduler () {
mConferenceScheduler->removeListener(mConferenceSchedulerListener);
}
std::shared_ptr<linphone::ConferenceScheduler> ConferenceSchedulerHandler::getConferenceScheduler(){
std::shared_ptr<linphone::ConferenceScheduler> ConferenceScheduler::getConferenceScheduler(){
return mConferenceScheduler;
}
void ConferenceSchedulerHandler::onStateChanged(const std::shared_ptr<linphone::ConferenceScheduler> & conferenceScheduler, linphone::ConferenceSchedulerState state) {
void ConferenceScheduler::onStateChanged(linphone::ConferenceSchedulerState state) {
emit stateChanged(state);
qWarning() << "ConferenceSchedulerHandler::onStateChanged : " << (int)state;
qWarning() << "ConferenceScheduler::onStateChanged : " << (int)state;
if( state == linphone::ConferenceSchedulerState::Ready) {
std::shared_ptr<linphone::ChatRoomParams> params = CoreManager::getInstance()->getCore()->createDefaultChatRoomParams();
params->setBackend(linphone::ChatRoomBackend::Basic);
@ -57,6 +61,6 @@ void ConferenceSchedulerHandler::onStateChanged(const std::shared_ptr<linphone::
}
}
void ConferenceSchedulerHandler::onInvitationsSent(const std::shared_ptr<linphone::ConferenceScheduler> & conferenceScheduler, const std::list<std::shared_ptr<linphone::Address>> & failedInvitations) {
void ConferenceScheduler::onInvitationsSent( const std::list<std::shared_ptr<linphone::Address>> & failedInvitations) {
emit invitationsSent(failedInvitations);
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2021-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 CONFERENCE_SCHEDULER_H_
#define CONFERENCE_SCHEDULER_H_
#include <linphone++/linphone.hh>
#include <QDateTime>
#include <QObject>
class ConferenceSchedulerListener;
class ConferenceScheduler : public QObject {
Q_OBJECT
public:
static QSharedPointer<ConferenceScheduler> create(QObject *parent = Q_NULLPTR);
ConferenceScheduler (QObject * parent = nullptr);
virtual ~ConferenceScheduler ();
std::shared_ptr<linphone::ConferenceScheduler> getConferenceScheduler();
virtual void onStateChanged(linphone::ConferenceSchedulerState state);
virtual void onInvitationsSent(const std::list<std::shared_ptr<linphone::Address>> & failedInvitations);
signals:
void stateChanged(linphone::ConferenceSchedulerState state);
void invitationsSent(const std::list<std::shared_ptr<linphone::Address>> & failedInvitations);
private:
void connectTo(ConferenceSchedulerListener * listener);
std::shared_ptr<linphone::ConferenceScheduler> mConferenceScheduler;
std::shared_ptr<ConferenceSchedulerListener> mConferenceSchedulerListener;
};
Q_DECLARE_METATYPE(QSharedPointer<ConferenceScheduler>)
#endif

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2021-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 "ConferenceSchedulerListener.hpp"
#include <QQmlApplicationEngine>
#include "app/App.hpp"
#include "components/core/CoreManager.hpp"
// =============================================================================
ConferenceSchedulerListener::ConferenceSchedulerListener () : QObject(nullptr){
}
ConferenceSchedulerListener::~ConferenceSchedulerListener () {
}
void ConferenceSchedulerListener::onStateChanged(const std::shared_ptr<linphone::ConferenceScheduler> & conferenceScheduler, linphone::ConferenceSchedulerState state) {
emit stateChanged(state);
}
void ConferenceSchedulerListener::onInvitationsSent(const std::shared_ptr<linphone::ConferenceScheduler> & conferenceScheduler, const std::list<std::shared_ptr<linphone::Address>> & failedInvitations) {
emit invitationsSent(failedInvitations);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Belledonne Communications SARL.
* Copyright (c) 2021-2022 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
@ -18,23 +18,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONFERENCE_SCHEDULER_HANDLER_H_
#define CONFERENCE_SCHEDULER_HANDLER_H_
#ifndef CONFERENCE_SCHEDULER_LISTENER_H_
#define CONFERENCE_SCHEDULER_LISTENER_H_
#include <linphone++/linphone.hh>
#include <QDateTime>
#include <QObject>
class ConferenceSchedulerHandler : public QObject
, public linphone::ConferenceSchedulerListener
{
class ConferenceSchedulerListener : public QObject, public linphone::ConferenceSchedulerListener {
Q_OBJECT
public:
static std::shared_ptr<ConferenceSchedulerHandler> create(QObject *parent = Q_NULLPTR);
ConferenceSchedulerHandler (QObject * parent = nullptr);
~ConferenceSchedulerHandler ();
std::shared_ptr<linphone::ConferenceScheduler> getConferenceScheduler();
ConferenceSchedulerListener();
virtual ~ConferenceSchedulerListener();
virtual void onStateChanged(const std::shared_ptr<linphone::ConferenceScheduler> & conferenceScheduler, linphone::ConferenceSchedulerState state) override;
virtual void onInvitationsSent(const std::shared_ptr<linphone::ConferenceScheduler> & conferenceScheduler, const std::list<std::shared_ptr<linphone::Address>> & failedInvitations) override;
@ -42,13 +38,6 @@ public:
signals:
void stateChanged(linphone::ConferenceSchedulerState state);
void invitationsSent(const std::list<std::shared_ptr<linphone::Address>> & failedInvitations);
private:
std::shared_ptr<linphone::ConferenceScheduler> mConferenceScheduler;
std::weak_ptr<ConferenceSchedulerHandler> mSelf; // Used for Linphone Listener
};
Q_DECLARE_METATYPE(std::shared_ptr<ConferenceSchedulerHandler>)
#endif

View file

@ -21,7 +21,7 @@
#ifndef LDAP_MODEL_H_
#define LDAP_MODEL_H_
#include <QAbstractListModel>
#include <QObject>
#include <QDateTime>
#include <linphone++/linphone.hh>

View file

@ -32,10 +32,10 @@
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;
//auto previewModel = ParticipantDeviceModel::create(nullptr, true);
//mList << previewModel;
for(auto device : devices){
auto deviceModel = ParticipantDeviceModel::create(device, false);
auto deviceModel = ParticipantDeviceModel::create(device, isMe(device));
connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged);
mList << deviceModel;
}
@ -44,12 +44,12 @@ ParticipantDeviceListModel::ParticipantDeviceListModel (std::shared_ptr<linphone
ParticipantDeviceListModel::ParticipantDeviceListModel (CallModel * callModel, QObject *parent) : ProxyListModel(parent) {
if(callModel && callModel->isConference()) {
mCallModel = callModel;
auto conferenceModel = callModel->getConferenceModel();
auto previewModel = ParticipantDeviceModel::create(nullptr, true);
mList << previewModel;
auto conferenceModel = callModel->getConferenceSharedModel();
//auto previewModel = ParticipantDeviceModel::create(nullptr, true);
//mList << previewModel;
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices = conferenceModel->getConference()->getParticipantDeviceList();
for(auto device : devices){
auto deviceModel = ParticipantDeviceModel::create(device, false);
auto deviceModel = ParticipantDeviceModel::create(device, isMe(device));
connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged);
mList << deviceModel;
}
@ -63,33 +63,36 @@ ParticipantDeviceListModel::ParticipantDeviceListModel (CallModel * callModel, Q
updateDevices(devices);
qWarning() << "Instanciate Participant Device list model with " << mList.size() << " devices";
*/
connect(conferenceModel.get(), &ConferenceModel::participantAdded, this, &ParticipantDeviceListModel::onParticipantAdded);
connect(conferenceModel.get(), &ConferenceModel::participantRemoved, this, &ParticipantDeviceListModel::onParticipantRemoved);
connect(conferenceModel.get(), &ConferenceModel::participantDeviceAdded, this, &ParticipantDeviceListModel::onParticipantDeviceAdded);
connect(conferenceModel.get(), &ConferenceModel::participantDeviceRemoved, this, &ParticipantDeviceListModel::onParticipantDeviceRemoved);
connect(conferenceModel.get(), &ConferenceModel::participantDeviceJoined, this, &ParticipantDeviceListModel::onParticipantDeviceJoined);
connect(conferenceModel.get(), &ConferenceModel::participantDeviceLeft, this, &ParticipantDeviceListModel::onParticipantDeviceLeft);
connect(conferenceModel.get(), &ConferenceModel::conferenceStateChanged, this, &ParticipantDeviceListModel::onConferenceStateChanged);
connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaAvailabilityChanged, this, &ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged);
}
}
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);
//auto previewModel = ParticipantDeviceModel::create(nullptr, true);
beginResetModel();
qWarning() << "Update devices from participant";
mList.clear();
mList << previewModel;
//mList << previewModel;
for(auto device : devices){
auto deviceModel = ParticipantDeviceModel::create(device, false);
auto deviceModel = ParticipantDeviceModel::create(device, isMe(device));
connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged);
mList << deviceModel;
}
endResetModel();
emit countChanged();
emit layoutChanged();
}
void ParticipantDeviceListModel::updateDevices(const std::list<std::shared_ptr<linphone::ParticipantDevice>>& devices, const bool& isMe){
/*
QList<std::shared_ptr<ParticipantDeviceModel>> devicesToAdd;
//auto meDevices = mCallModel->getConferenceModel()->getConference()->getMe()->getDevices();
//auto meDevices = mCallModel->getConferenceSharedModel()->getConference()->getMe()->getDevices();
for(auto device : devices){
auto deviceAddress = device->getAddress();
//bool isMe = false;
@ -117,21 +120,96 @@ void ParticipantDeviceListModel::updateDevices(const std::list<std::shared_ptr<l
*/
}
bool ParticipantDeviceListModel::add(std::shared_ptr<linphone::ParticipantDevice> deviceToAdd){
qWarning() << "Adding device " << deviceToAdd->getAddress()->asString().c_str();
for(auto item : mList) {
auto deviceModel = item.objectCast<ParticipantDeviceModel>();
if(deviceModel->getDevice() == deviceToAdd) {
qWarning() << "Device already exist. Send video update event";
emit deviceModel->videoEnabledChanged();
return false;
}
}
auto deviceModel = ParticipantDeviceModel::create(deviceToAdd, isMe(deviceToAdd));
connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged);
ProxyListModel::add<ParticipantDeviceModel>(deviceModel);
qWarning() << "Device added. Count=" << mList.count();
return true;
}
bool ParticipantDeviceListModel::remove(std::shared_ptr<const linphone::ParticipantDevice> deviceToRemove){
int row = 0;
for(auto device : mList){
if( device.objectCast<ParticipantDeviceModel>()->getDevice() == deviceToRemove){
removeRow(row);
return true;
}else
++row;
}
return false;
}
QSharedPointer<ParticipantDeviceModel> ParticipantDeviceListModel::get(std::shared_ptr<const linphone::ParticipantDevice> deviceToGet, int * index){
int row = 0;
for(auto item : mList){
auto device = item.objectCast<ParticipantDeviceModel>();
if( device->getDevice() == deviceToGet){
if(index)
*index = row;
return device;
}else
++row;
}
return nullptr;
}
bool ParticipantDeviceListModel::isMe(std::shared_ptr<linphone::ParticipantDevice> deviceToCheck)const{
if(mCallModel){
auto devices = mCallModel->getConferenceModel()->getConference()->getMe()->getDevices();
auto deviceToCheckAddress = deviceToCheck->getAddress();
for(auto device : devices){
if(deviceToCheckAddress == device->getAddress())
return true;
}
}
return false;
}
bool ParticipantDeviceListModel::isMeAlone() const{
for(auto item : mList){
auto device = item.objectCast<ParticipantDeviceModel>();
if( !isMe(device->getDevice()))
return false;
}
return true;
}
void ParticipantDeviceListModel::onSecurityLevelChanged(std::shared_ptr<const linphone::Address> device){
emit securityLevelChanged(device);
}
//----------------------------------------------------------------------------------------------------------
void ParticipantDeviceListModel::onParticipantAdded(const std::shared_ptr<const linphone::Participant> & participant){
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices = participant->getDevices() ;
for(auto device : devices)
add(device);
}
void ParticipantDeviceListModel::onParticipantRemoved(const std::shared_ptr<const linphone::Participant> & participant){
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices = participant->getDevices() ;
for(auto device : devices)
remove(device);
}
void ParticipantDeviceListModel::onParticipantDeviceAdded(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
auto conferenceModel = mCallModel->getConferenceModel();
qWarning() << "Adding new device : " << mList.count();
auto conferenceModel = mCallModel->getConferenceSharedModel();
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices = conferenceModel->getConference()->getParticipantDeviceList();
for(auto realParticipantDevice : devices){
if( realParticipantDevice == participantDevice){
auto deviceModel = ParticipantDeviceModel::create(realParticipantDevice, false);
connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged);
add(deviceModel);
add(realParticipantDevice);
return;
}
}
@ -139,31 +217,38 @@ void ParticipantDeviceListModel::onParticipantDeviceAdded(const std::shared_ptr<
}
void ParticipantDeviceListModel::onParticipantDeviceRemoved(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "Removing participant";
int row = 0;
for(auto device : mList){
if( device.objectCast<ParticipantDeviceModel>()->getDevice() == participantDevice){
removeRow(row);
return;
}
++row;
}
qWarning() << "No participant device found from const linphone::ParticipantDevice at onParticipantDeviceRemoved";
qWarning() << "Removing participant device : " << mList.count();
if(!remove(participantDevice))
qWarning() << "No participant device found from const linphone::ParticipantDevice at onParticipantDeviceRemoved";
}
void ParticipantDeviceListModel::onParticipantDeviceJoined(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "onParticipantDeviceJoined is not yet implemented. Current participants count: " << mList.size();
onParticipantDeviceAdded(participantDevice);
/*
for(auto item : mList) {
auto device = item.objectCast<ParticipantDeviceModel>();
if(device->getDevice() == participantDevice) {
emit device->videoEnabledChanged();
return;
}
}*/
}
void ParticipantDeviceListModel::onParticipantDeviceLeft(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
qWarning() << "onParticipantDeviceLeft is not yet implemented. Current participants count: " << mList.size();
for(auto item : mList) {
auto device = item.objectCast<ParticipantDeviceModel>();
if(device->getDevice() == participantDevice) {
emit device->videoEnabledChanged();
return;
}
}
}
void ParticipantDeviceListModel::onConferenceStateChanged(linphone::Conference::State newState){
if(newState == linphone::Conference::State::Created){
if(mCallModel && mCallModel->isConference()) {
auto conferenceModel = mCallModel->getConferenceModel();
updateDevices(mCallModel->getConferenceModel()->getConference()->getMe()->getDevices(), true);
auto conferenceModel = mCallModel->getConferenceSharedModel();
updateDevices(conferenceModel->getConference()->getMe()->getDevices(), true);
updateDevices(conferenceModel->getConference()->getParticipantDeviceList(), false);
}
@ -188,4 +273,10 @@ void ParticipantDeviceListModel::onConferenceStateChanged(linphone::Conference::
}
*/
}
}
void ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
auto device = get(participantDevice);
if(device)
emit device->videoEnabledChanged();
}

View file

@ -42,13 +42,23 @@ public:
void updateDevices(std::shared_ptr<linphone::Participant> participant);
void updateDevices(const std::list<std::shared_ptr<linphone::ParticipantDevice>>& devices, const bool& isMe);
bool add(std::shared_ptr<linphone::ParticipantDevice> deviceToAdd);
bool remove(std::shared_ptr<const linphone::ParticipantDevice> deviceToAdd);
QSharedPointer<ParticipantDeviceModel> get(std::shared_ptr<const linphone::ParticipantDevice> deviceToGet, int * index = nullptr);
bool isMe(std::shared_ptr<linphone::ParticipantDevice> device)const;
bool isMeAlone() const;
public slots:
void onSecurityLevelChanged(std::shared_ptr<const linphone::Address> device);
void onParticipantAdded(const std::shared_ptr<const linphone::Participant> & participant);
void onParticipantRemoved(const std::shared_ptr<const linphone::Participant> & participant);
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);
void onParticipantDeviceLeft(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
void onConferenceStateChanged(linphone::Conference::State newState);
void onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
signals:
void securityLevelChanged(std::shared_ptr<const linphone::Address> device);

View file

@ -84,6 +84,10 @@ QString ParticipantDeviceModel::getName() const{
return mParticipantDevice ? Utils::coreStringToAppString(mParticipantDevice->getName()) : "NoName";
}
QString ParticipantDeviceModel::getDisplayName() const{
return mParticipantDevice ? Utils::getDisplayName(mParticipantDevice->getAddress()) : "";
}
int ParticipantDeviceModel::getSecurityLevel() const{
if( mParticipantDevice) {
int security = (int)mParticipantDevice->getSecurityLevel();
@ -106,9 +110,9 @@ std::shared_ptr<linphone::ParticipantDevice> ParticipantDeviceModel::getDevice(
}
bool ParticipantDeviceModel::isVideoEnabled() const{
if(mParticipantDevice)
qWarning() << "VideoEnabled: " << (int)mParticipantDevice->getStreamAvailability(linphone::StreamType::Video);
return mParticipantDevice && mParticipantDevice->getStreamAvailability(linphone::StreamType::Video);
bool enabled = mParticipantDevice && mParticipantDevice->getStreamAvailability(linphone::StreamType::Video) || isMe();// && mCall && mCall->getVideoEnabled();
qWarning() << "VideoEnabled: " << enabled;
return enabled;
}
bool ParticipantDeviceModel::isMe() const{
@ -130,6 +134,7 @@ void ParticipantDeviceModel::onConferenceJoined(const std::shared_ptr<linphone::
void ParticipantDeviceModel::onConferenceLeft(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice) {
}
void ParticipantDeviceModel::onStreamCapabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::MediaDirection direction, linphone::StreamType streamType) {
emit videoEnabledChanged();
}
void ParticipantDeviceModel::onStreamAvailabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool available, linphone::StreamType streamType) {
emit videoEnabledChanged();

View file

@ -44,6 +44,7 @@ public:
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 displayName READ getDisplayName CONSTANT)
Q_PROPERTY(QString name READ getName CONSTANT)
Q_PROPERTY(QString address READ getAddress CONSTANT)
Q_PROPERTY(int securityLevel READ getSecurityLevel NOTIFY securityLevelChanged)
@ -52,6 +53,7 @@ public:
Q_PROPERTY(bool isMe READ isMe CONSTANT)
QString getName() const;
QString getDisplayName() const;
QString getAddress() const;
int getSecurityLevel() const;
time_t getTimeOfJoining() const;

View file

@ -30,7 +30,7 @@
// =============================================================================
ParticipantDeviceProxyModel::ParticipantDeviceProxyModel (QObject *parent) : QSortFilterProxyModel(parent){
ParticipantDeviceProxyModel::ParticipantDeviceProxyModel (QObject *parent) : SortFilterProxyModel(parent){
}
bool ParticipantDeviceProxyModel::filterAcceptsRow (
@ -39,10 +39,15 @@ bool ParticipantDeviceProxyModel::filterAcceptsRow (
) const {
Q_UNUSED(sourceRow)
Q_UNUSED(sourceParent)
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
const ParticipantDeviceModel *device = index.data().value<ParticipantDeviceModel *>();
return device && (isShowMe() || !device->isMe());
auto listModel = qobject_cast<ParticipantDeviceListModel*>(sourceModel());
/*
if(mFilterType == 1 && listModel->rowCount() <= 2){
return sourceRow == 0;
}else{*/
const QModelIndex index = listModel->index(sourceRow, 0, sourceParent);
const ParticipantDeviceModel *device = index.data().value<ParticipantDeviceModel *>();
return device && (isShowMe() || !device->isMe());
//}
}
bool ParticipantDeviceProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
@ -63,27 +68,21 @@ CallModel * ParticipantDeviceProxyModel::getCallModel() const{
return mCallModel;
}
int ParticipantDeviceProxyModel::getCount() const{
ParticipantDeviceListModel* devices = qobject_cast<ParticipantDeviceListModel*>(sourceModel());
if(devices)
return devices->rowCount();
else
return 0;
}
bool ParticipantDeviceProxyModel::isShowMe() const{
return mShowMe;
}
void ParticipantDeviceProxyModel::setCallModel(CallModel * callModel){
setFilterType(1);
mCallModel = callModel;
auto sourceModel = new ParticipantDeviceListModel(mCallModel);
connect(sourceModel, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::countChanged);
connect(sourceModel, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::onCountChanged);
setSourceModel(sourceModel);
emit countChanged();
}
void ParticipantDeviceProxyModel::setParticipant(ParticipantModel * participant){
setFilterType(0);
auto sourceModel = participant->getParticipantDevices().get();
connect(sourceModel, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::countChanged);
setSourceModel(sourceModel);
@ -95,4 +94,11 @@ void ParticipantDeviceProxyModel::setShowMe(const bool& show){
mShowMe = show;
emit showMeChanged();
}
}
void ParticipantDeviceProxyModel::onCountChanged(){
auto listModel = qobject_cast<ParticipantDeviceListModel*>(sourceModel());
if(mFilterType == 1 || mFilterType == 2){
//if( listModel->getCount()
}
}

View file

@ -27,26 +27,24 @@
#include <QObject>
#include <QDateTime>
#include <QString>
#include <QSortFilterProxyModel>
#include "app/proxyModel/SortFilterProxyModel.hpp"
class ParticipantDeviceListModel;
class ParticipantDeviceModel;
class ParticipantModel;
class CallModel;
class ParticipantDeviceProxyModel : public QSortFilterProxyModel {
class ParticipantDeviceProxyModel : public SortFilterProxyModel {
Q_OBJECT
public:
Q_PROPERTY(CallModel * callModel READ getCallModel WRITE setCallModel NOTIFY callModelChanged)
Q_PROPERTY(int count READ getCount NOTIFY countChanged)
Q_PROPERTY(bool showMe READ isShowMe WRITE setShowMe NOTIFY showMeChanged)
ParticipantDeviceProxyModel (QObject *parent = nullptr);
Q_INVOKABLE ParticipantDeviceModel* getAt(int row);
CallModel * getCallModel() const;
Q_INVOKABLE int getCount() const;
bool isShowMe() const;
@ -54,16 +52,18 @@ public:
void setParticipant(ParticipantModel * participant);
void setShowMe(const bool& show);
public slots:
void onCountChanged();
signals:
void callModelChanged();
void countChanged();
void showMeChanged();
protected:
virtual bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
virtual bool lessThan (const QModelIndex &left, const QModelIndex &right) const override;
std::shared_ptr<ParticipantDeviceListModel> mDevices;
QSharedPointer<ParticipantDeviceListModel> mDevices;
CallModel * mCallModel;
bool mShowMe = false;
};

View file

@ -61,7 +61,7 @@ QVariantList ParticipantProxyModel::getParticipants() const{
QVariantList participants;
ParticipantListModel * list = qobject_cast<ParticipantListModel*>(sourceModel());
for(int i = 0 ; i < list->rowCount() ; ++i)
participants << QVariant::fromValue(list->getAt(i));
participants << QVariant::fromValue(list->getAt<ParticipantModel>(i));
return participants;
}

View file

@ -17,15 +17,15 @@
* 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 "SearchHandler.hpp"
#include "SearchListener.hpp"
#include "linphone/api/c-search-result.h"
// =============================================================================
SearchHandler::SearchHandler(QObject * parent) : QObject(parent){
SearchListener::SearchListener(QObject * parent) : QObject(parent){
}
void SearchHandler::onSearchResultsReceived(const std::shared_ptr<linphone::MagicSearch> & magicSearch){
void SearchListener::onSearchResultsReceived(const std::shared_ptr<linphone::MagicSearch> & magicSearch){
emit searchReceived(magicSearch->getLastSearch());
}

View file

@ -18,21 +18,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SEARCH_HANDLER_H_
#define SEARCH_HANDLER_H_
#ifndef SEARCH_LISTENER_H_
#define SEARCH_LISTENER_H_
#include <QObject>
#include <linphone++/linphone.hh>
#include <list>
// =============================================================================
class SearchHandler : public QObject, public linphone::MagicSearchListener{
class SearchListener : public QObject, public linphone::MagicSearchListener{
Q_OBJECT
public:
SearchHandler(QObject * parent = nullptr);
SearchListener(QObject * parent = nullptr);
virtual void onSearchResultsReceived(const std::shared_ptr<linphone::MagicSearch> & magicSearch);
signals:
void searchReceived(std::list<std::shared_ptr<linphone::SearchResult>> );
};
Q_DECLARE_METATYPE(std::shared_ptr<linphone::SearchResult>);
#endif // SEARCH_HANDLER_H_
#endif

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
* Copyright (c) 2010-2022 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
@ -46,11 +46,11 @@ using namespace std;
// -----------------------------------------------------------------------------
SearchSipAddressesModel::SearchSipAddressesModel (QObject *parent) : QAbstractListModel(parent) {
SearchSipAddressesModel::SearchSipAddressesModel (QObject *parent) : ProxyListModel(parent) {
mMagicSearch = CoreManager::getInstance()->getCore()->createMagicSearch();
mSearch = std::make_shared<SearchHandler>(this);
QObject::connect(mSearch.get(), &SearchHandler::searchReceived, this, &SearchSipAddressesModel::searchReceived, Qt::QueuedConnection);
mSearch = std::make_shared<SearchListener>(this);
QObject::connect(mSearch.get(), &SearchListener::searchReceived, this, &SearchSipAddressesModel::searchReceived, Qt::QueuedConnection);
mMagicSearch->addListener(mSearch);
}
@ -61,67 +61,23 @@ SearchSipAddressesModel::~SearchSipAddressesModel(){
// -----------------------------------------------------------------------------
int SearchSipAddressesModel::rowCount (const QModelIndex &) const {
return mAddresses.count();
}
QHash<int, QByteArray> SearchSipAddressesModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$sipAddress";
return roles;
}
QVariant SearchSipAddressesModel::data (const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mAddresses.count())
return QVariant();
if (role == Qt::DisplayRole)
return QVariant::fromValue(mAddresses[row].get());
return QVariant();
}
// -----------------------------------------------------------------------------
bool SearchSipAddressesModel::removeRow (int row, const QModelIndex &parent) {
return removeRows(row, 1, parent);
}
bool SearchSipAddressesModel::removeRows (int row, int count, const QModelIndex &parent) {
int limit = row + count - 1;
if (row < 0 || count < 0 || limit >= mAddresses.count())
return false;
beginRemoveRows(parent, row, limit);
for (int i = 0; i < count; ++i)
mAddresses.removeAt(row);
endRemoveRows();
return true;
}
void SearchSipAddressesModel::setFilter(const QString& filter){
mMagicSearch->getContactListFromFilterAsync(filter.toStdString(),"");
//searchReceived(mMagicSearch->getContactListFromFilter(Utils::appStringToCoreString(filter),"")); // Just to show how to use sync method
}
void SearchSipAddressesModel::searchReceived(std::list<std::shared_ptr<linphone::SearchResult>> results){
QList<std::shared_ptr<SearchResultModel> > addresses;
QList<QSharedPointer<QObject> > addresses;
for(auto it = results.begin() ; it != results.end() ; ++it){
auto linphoneFriend = (*it)->getFriend();
auto address = (*it)->getAddress();
if( linphoneFriend || address)
addresses << std::make_shared<SearchResultModel>(linphoneFriend,address );
addresses << QSharedPointer<SearchResultModel>::create(linphoneFriend,address );
}
beginResetModel();
mAddresses.clear();
mAddresses = addresses;
if(mAddresses.size() > 0 )// remove self
mAddresses.pop_back();
mList.clear();
mList = addresses;
if(mList.size() > 0 )// remove self
mList.pop_back();
endResetModel();
}

View file

@ -21,45 +21,35 @@
#ifndef SEARCH_SIP_ADDRESSES_MODEL_H_
#define SEARCH_SIP_ADDRESSES_MODEL_H_
#include <QAbstractListModel>
#include <QDateTime>
#include <list>
#include <linphone++/linphone.hh>
#include "SearchHandler.hpp"
#include "SearchListener.hpp"
#include "app/proxyModel/ProxyListModel.hpp"
// =============================================================================
class SearchResultModel;
class SearchSipAddressesModel : public QAbstractListModel {
class SearchSipAddressesModel : public ProxyListModel {
Q_OBJECT
public:
SearchSipAddressesModel (QObject *parent = Q_NULLPTR);
~SearchSipAddressesModel();
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;
Q_INVOKABLE void setFilter (const QString &pattern);
QList<std::shared_ptr<SearchResultModel> > mAddresses;
//QList<std::shared_ptr<SearchResultModel> > mAddresses;
// And instance of Magic search
std::shared_ptr<linphone::MagicSearch> mMagicSearch;
// Callback when searching
std::shared_ptr<SearchHandler> mSearch;
std::shared_ptr<SearchListener> mSearch;
public slots:
void searchReceived(std::list<std::shared_ptr<linphone::SearchResult>> results);
private:
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
};
Q_DECLARE_METATYPE(SearchSipAddressesModel *);

View file

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

View file

@ -29,31 +29,23 @@
// =============================================================================
TunnelConfigListModel::TunnelConfigListModel (std::shared_ptr<linphone::Tunnel> tunnel, QObject *parent) : QAbstractListModel(parent) {
TunnelConfigListModel::TunnelConfigListModel (std::shared_ptr<linphone::Tunnel> tunnel, QObject *parent) : ProxyListModel(parent) {
std::list<std::shared_ptr<linphone::TunnelConfig>> tunnelConfigs = tunnel->getServers() ;
for(auto config : tunnelConfigs){
auto configModel = std::make_shared<TunnelConfigModel>(config);
auto configModel = QSharedPointer<TunnelConfigModel>::create(config);
mList << configModel;
}
if( mList.size() == 0) {
mList << std::make_shared<TunnelConfigModel>(linphone::Factory::get()->createTunnelConfig());
mList << QSharedPointer<TunnelConfigModel>::create(linphone::Factory::get()->createTunnelConfig());
}
}
int TunnelConfigListModel::rowCount (const QModelIndex &index) const{
return mList.count();
}
int TunnelConfigListModel::count(){
return mList.count();
}
void TunnelConfigListModel::updateTunnelConfigs(std::shared_ptr<linphone::Tunnel> tunnel){
std::list<std::shared_ptr<linphone::TunnelConfig>> tunnelConfigs = tunnel->getServers() ;
beginResetModel();
mList.clear();
for(auto config : tunnelConfigs){
mList << std::make_shared<TunnelConfigModel>(config);
mList << QSharedPointer<TunnelConfigModel>::create(config);
}
endResetModel();
emit layoutChanged();
@ -62,7 +54,7 @@ void TunnelConfigListModel::updateTunnelConfigs(std::shared_ptr<linphone::Tunnel
bool TunnelConfigListModel::apply(std::shared_ptr<linphone::Tunnel> tunnel){
tunnel->cleanServers();
for(auto config : mList){
tunnel->addServer(config->getTunnelConfig());
tunnel->addServer(config.objectCast<TunnelConfigModel>()->getTunnelConfig());
}
updateTunnelConfigs(tunnel);
return true;
@ -71,7 +63,7 @@ bool TunnelConfigListModel::apply(std::shared_ptr<linphone::Tunnel> tunnel){
void TunnelConfigListModel::addTunnelConfig(){
int row = rowCount();
beginInsertRows(QModelIndex(),row,row);
mList << std::make_shared<TunnelConfigModel>(linphone::Factory::get()->createTunnelConfig());
mList << QSharedPointer<TunnelConfigModel>::create(linphone::Factory::get()->createTunnelConfig());
endInsertRows();
}
@ -84,41 +76,3 @@ void TunnelConfigListModel::removeTunnelConfig(std::shared_ptr<linphone::Tunnel>
tunnel->removeServer(model->getTunnelConfig());
}
}
QHash<int, QByteArray> TunnelConfigListModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$tunnelConfig";
return roles;
}
QVariant TunnelConfigListModel::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 TunnelConfigListModel::removeRow (int row, const QModelIndex &parent){
return removeRows(row, 1, parent);
}
bool TunnelConfigListModel::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;
}

View file

@ -27,36 +27,23 @@
#include <QObject>
#include <QDateTime>
#include <QString>
#include <QAbstractListModel>
#include "app/proxyModel/ProxyListModel.hpp"
class TunnelConfigModel;
class TunnelConfigListModel : public QAbstractListModel {
class TunnelConfigListModel : public ProxyListModel {
Q_OBJECT
public:
TunnelConfigListModel (std::shared_ptr<linphone::Tunnel> tunnel, QObject *parent = nullptr);
int rowCount (const QModelIndex &index = QModelIndex()) const override;
int count();
void updateTunnelConfigs(std::shared_ptr<linphone::Tunnel> tunnel);
bool apply(std::shared_ptr<linphone::Tunnel> tunnel);
void addTunnelConfig();
void removeTunnelConfig(std::shared_ptr<linphone::Tunnel> tunnel, TunnelConfigModel * model);
virtual QHash<int, QByteArray> roleNames () const override;
virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
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<TunnelConfigModel>> mList;
};
Q_DECLARE_METATYPE(std::shared_ptr<TunnelConfigListModel>)
Q_DECLARE_METATYPE(QSharedPointer<TunnelConfigListModel>)
#endif // TUNNEL_CONFIG_LIST_MODEL_H_

View file

@ -70,6 +70,6 @@ private:
};
Q_DECLARE_METATYPE(std::shared_ptr<TunnelConfigModel>)
Q_DECLARE_METATYPE(QSharedPointer<TunnelConfigModel>)
#endif // TUNNEL_CONFIG_MODEL

View file

@ -27,6 +27,9 @@ Loader{
property int fitHeight: active && item ? item.fitHeight + ChatCalendarMessageStyle.heightMargin*2 : 0
property int fitWidth: active && item ? Math.max(item.fitWidth, maxWidth/2) + ChatCalendarMessageStyle.widthMargin*2 : 0
property bool containsMouse: false
property int gotoButtonMode: -1 //-1: hide, 0:goto, 1:MoreInfo
property bool isExpanded : false
width: parent.width
height: fitHeight
@ -35,7 +38,7 @@ Loader{
sourceComponent: MouseArea{
id: loadedItem
property int fitHeight: layout.fitHeight
property int fitHeight: layout.fitHeight + ChatCalendarMessageStyle.heightMargin
property int fitWidth: layout.fitWidth
anchors.fill: parent
@ -139,13 +142,40 @@ Loader{
text: mainItem.conferenceInfoModel.displayNamesToString
}
ActionButton{
visible: mainItem.gotoButtonMode >= 0
Layout.preferredHeight: iconSize
Layout.preferredWidth: height
isCustom: true
colorSet: ChatCalendarMessageStyle.gotoButton
colorSet: mainItem.gotoButtonMode == 0 ? ChatCalendarMessageStyle.gotoButton : ChatCalendarMessageStyle.infoButton
backgroundRadius: width/2
onClicked: mainItem.isExpanded = !mainItem.isExpanded
}
}
Text{
id: descriptionTitle
visible: mainItem.isExpanded
Layout.fillWidth: true
Layout.minimumWidth: implicitWidth
Layout.leftMargin: 10
color: ChatCalendarMessageStyle.subject.color
font.pointSize: ChatCalendarMessageStyle.subject.pointSize
font.weight: Font.Bold
text: 'Description :'
}
Text{
id: description
visible: mainItem.isExpanded
Layout.fillWidth: true
Layout.minimumWidth: implicitWidth
Layout.leftMargin: 10
color: ChatCalendarMessageStyle.description.color
font.pointSize: ChatCalendarMessageStyle.description.pointSize
//font.weight: Font.Bold
elide: Text.ElideRight
maximumLineCount: 100
text: mainItem.conferenceInfoModel.description
}
}
}
}

View file

@ -119,7 +119,7 @@ Column {
Rectangle {
id: content
readonly property bool isDownloadable: Boolean($codec.downloadUrl)
readonly property bool isDownloadable: Boolean($modelData.downloadUrl)
Drag.active: dragArea.held
Drag.source: dragArea
@ -145,23 +145,23 @@ Column {
CodecAttribute {
Layout.preferredWidth: CodecsViewerStyle.column.mimeWidth
text: $codec.mime
text: $modelData.mime
}
CodecAttribute {
Layout.preferredWidth: CodecsViewerStyle.column.encoderDescriptionWidth
text: $codec.encoderDescription || ''
text: $modelData.encoderDescription || ''
}
CodecAttribute {
Layout.preferredWidth: CodecsViewerStyle.column.clockRateWidth
text: $codec.clockRate || ''
text: $modelData.clockRate || ''
}
NumericField {
Layout.preferredWidth: CodecsViewerStyle.column.bitrateWidth
readOnly: content.isDownloadable || !$codec.isVbr
text: $codec.bitrate || ''
readOnly: content.isDownloadable || !$modelData.isVbr
text: $modelData.bitrate || ''
onEditingFinished: view.model.setBitrate(index, text)
}
@ -169,7 +169,7 @@ Column {
TextField {
Layout.preferredWidth: CodecsViewerStyle.column.recvFmtpWidth
readOnly: content.isDownloadable
text: $codec.recvFmtp || ''
text: $modelData.recvFmtp || ''
onEditingFinished: view.model.setRecvFmtp(index, text)
}
@ -177,10 +177,10 @@ Column {
Switch {
Layout.fillWidth: true
checked: Boolean($codec.enabled)
checked: Boolean($modelData.enabled)
onClicked: !checked && content.isDownloadable
? downloadRequested($codec)
? downloadRequested($modelData)
: view.model.enableCodec(index, !checked)
}
}

View file

@ -38,7 +38,7 @@ Item {
model.clear()
sipAddresses.forEach(function (sipAddress) {
model.append({ $sipAddress: sipAddress })
model.append({ $modelData: sipAddress })
})
}
@ -97,7 +97,7 @@ Item {
elide: Text.ElideRight
font.pointSize: SipAddressesMenuStyle.entry.text.pointSize
height: parent.height
text: $sipAddress
text: $modelData
verticalAlignment: Text.AlignVCenter
}
@ -109,9 +109,9 @@ Item {
onClicked: {
menu.close()
if( menu.callback)
menu.callback($sipAddress)
menu.callback($modelData)
else
sipAddressesMenu.sipAddressClicked($sipAddress)
sipAddressesMenu.sipAddressClicked($modelData)
}
}
}

View file

@ -49,6 +49,11 @@ QtObject {
property int pointSize: Units.dp * 11
property color color: ColorsList.add(sectionName+'_subject', 'j').color
}
property QtObject description: QtObject {
property int spacing: 5
property int pointSize: Units.dp * 9
property color color: ColorsList.add(sectionName+'_description', 'j').color
}
property QtObject participants: QtObject {
property int spacing: 5
property int pointSize: Units.dp * 9
@ -68,6 +73,17 @@ QtObject {
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_h', icon, 's_h_b_fg').color
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_p', icon, 's_p_b_fg').color
}
property QtObject infoButton: QtObject{
property int iconSize: 35
property string name : 'info'
property string icon : 'menu_info_custom'
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_b_n', icon, 'me_n_b_bg').color
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_b_h', icon, 'me_h_b_bg').color
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_b_p', icon, 'me_p_b_bg').color
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_n', icon, 'me_n_b_fg').color
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_h', icon, 'me_h_b_fg').color
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_p', icon, 'me_p_b_fg').color
}
property QtObject organizer: QtObject {
property color color: ColorsList.add(sectionName+'_conference_organizer', 'j').color

View file

@ -127,7 +127,7 @@ ScrollableListView {
})
Icon{
visible: modelData.secure>0 &&
(sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler({sipAddres:$sipAddress}) : true)
(sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler({sipAddres:$modelData}) : true)
icon: modelData.secure === 2?'secure_level_2':'secure_level_1'
iconSize:parent.height/2
anchors.top:parent.top
@ -293,7 +293,7 @@ ScrollableListView {
}
Icon{
visible: modelData.secure>0 &&
(sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler({sipAddres:$sipAddress}) : true)
(sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler({sipAddres:$modelData}) : true)
icon: modelData.secure === 2?'secure_level_2':'secure_level_1'
iconSize: parent.height/2
anchors.top:parent.top

View file

@ -284,21 +284,20 @@ ScrollableListView {
active: sipAddressesView.showSwitch // Resolve a random Qt crash from using indicator on switch. This way, switch is not loaded.
// https://bugreports.qt.io/browse/QTBUG-82285.
}
Repeater {
model: sipAddressesView.actions
ActionButton {
isCustom: true
backgroundRadius: 90
colorSet: $modelData.colorSet
colorSet: sipAddressesView.actions[index].colorSet
tooltipText:$modelData.tooltipText?$modelData.tooltipText:''
visible: $modelData.visible
visible: sipAddressesView.actions[index].visible
onClicked: {// Do not use $modelData on functions : Qt bug
sipAddressesView.actions[index].handler(sipAddressEntry.entry)
}
Icon{
visible: $modelData.secure>0 &&
visible: sipAddressesView.actions[index].secure>0 &&
// Do not use $modelData on functions : Qt bug
(sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler(sipAddressEntry.entry) : true)
icon: 'secure_on'

View file

@ -31,6 +31,7 @@ Window {
});
readonly property bool chatIsOpened: !rightPaned.isClosed()
readonly property bool callsIsOpened: !mainPaned.isClosed()
// ---------------------------------------------------------------------------
@ -76,6 +77,7 @@ Window {
// ---------------------------------------------------------------------------
Paned {
id: mainPaned
anchors.fill: parent
defaultChildAWidth: CallsWindowStyle.callsList.defaultWidth
maximumLeftLimit: CallsWindowStyle.callsList.maximumWidth
@ -86,6 +88,7 @@ Window {
// -------------------------------------------------------------------------
childA: Rectangle {
id: leftPaned
anchors.fill: parent
color: CallsWindowStyle.callsList.color
@ -140,6 +143,16 @@ Window {
}
}
}
ActionButton {
anchors.right: parent.right
anchors.rightMargin: 15
anchors.verticalCenter: parent.verticalCenter
isCustom: true
backgroundRadius: 4
colorSet: CallsWindowStyle.callsList.closeButton
onClicked: mainPaned.close()
}
}
Calls {
@ -240,6 +253,8 @@ Window {
id: videoConference
VideoConference {
callModel: window.call
listCallsOpened: window.callsIsOpened
onOpenListCallsRequest: mainPaned.open()
}
}

View file

@ -1,6 +1,7 @@
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQml.Models 2.12
import QtGraphicalEffects 1.12
import Common 1.0
import Common.Styles 1.0
@ -14,6 +15,7 @@ import App.Styles 1.0
// Temp
import 'Incall.js' as Logic
import 'qrc:/ui/scripts/Utils/utils.js' as Utils
// =============================================================================
@ -21,24 +23,15 @@ Rectangle {
id: conference
property CallModel callModel
property ConferenceModel conferenceModel: callModel && callModel.getConferenceModel()
property var _fullscreen: null
/*
onCallModelChanged: if(callModel) {
grid.setParticipantDevicesMode()
}else
grid.setTestMode()
*/
property bool listCallsOpened: true
signal openListCallsRequest()
// ---------------------------------------------------------------------------
color: VideoConferenceStyle.backgroundColor
/*
Component.onCompleted: {
if(!callModel){
grid.setTestMode()
}else
grid.setParticipantDevicesMode()
}
*/
Connections {
target: callModel
@ -65,17 +58,29 @@ Rectangle {
isCustom: true
backgroundRadius: width/2
colorSet: VideoConferenceStyle.buttons.callsList
visible: !listCallsOpened
onClicked: openListCallsRequest()
}
ActionButton{
id: keypadButton
isCustom: true
backgroundRadius: width/2
colorSet: VideoConferenceStyle.buttons.dialpad
onClicked: telKeypad.visible = !telKeypad.visible
}
// Title
Text{
Timer{
id: elapsedTimeRefresher
running: true
interval: 1000
repeat: true
onTriggered: parent.elaspedTime = ' - ' +Utils.formatElapsedTime(conferenceModel.getElapsedSeconds())
}
property string elaspedTime
horizontalAlignment: Qt.AlignHCenter
Layout.fillWidth: true
text: 'Sujet de la conférence' + ' - ' + '02:23:12'
text: conferenceModel.subject+ elaspedTime
color: VideoConferenceStyle.title.color
font.pointSize: VideoConferenceStyle.title.pointSize
}
@ -169,20 +174,29 @@ Rectangle {
delegate: Rectangle{
id: avatarCell
property ParticipantDeviceModel currentDevice: gridModel.participantDevices.getAt(index)
onCurrentDeviceChanged: console.log("currentDevice changed: " +currentDevice +", me:"+currentDevice.isMe+" ["+index+"]")
onCurrentDeviceChanged: console.log("currentDevice changed: " +currentDevice + (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 : ''
radius: grid.radius
radius: 50//grid.radius
height: grid.cellHeight - 5
width: grid.cellWidth - 5
Component.onCompleted: console.log("Completed: ["+index+"] " +currentDevice.peerAddress+", isMe:"+currentDevice.isMe)
Component.onCompleted: console.log("Completed: ["+index+"] " +(currentDevice?currentDevice.peerAddress+", isMe:"+currentDevice.isMe : '') )
Rectangle{
id: showArea
anchors.fill: parent
radius: 50
visible:false
color: 'red'
}
Item {
id: container
anchors.fill: parent
anchors.margins: CallStyle.container.margins
visible: conference.callModel
//anchors.margins: CallStyle.container.margins
//visible: conference.callModel
visible: false
//Layout.fillWidth: true
//Layout.fillHeight: true
//Layout.margins: CallStyle.container.margins
@ -218,14 +232,9 @@ Rectangle {
onT_fullscreenChanged: console.log("_fullscreen changed: " +t_fullscreen+ " ["+index+"]")
onTCallModelChanged: console.log("CallModel changed: " +tCallModel+ " ["+index+"]")
active: !resetActive //avatarCell.currentDevice && (avatarCell.currentDevice.videoEnabled && !conference._fullscreen)
onActiveChanged: {console.log("Active Changed: "+active+ " ["+index+"]")
if(!active && resetActive){
resetActive = false
active = true
}
}
property int cameraMode: avatarCell.currentDevice ?
active: !resetActive && avatarCell.currentDevice && (avatarCell.currentDevice.videoEnabled && !conference._fullscreen)
property int cameraMode: isVideoEnabled ?
avatarCell.currentDevice.isMe ? 1
: 2
: 0
@ -242,10 +251,20 @@ Rectangle {
//height: container.height
//width: container.width
anchors.fill: parent
onRequestNewRenderer: {cameraLoader.resetActive = true}
onRequestNewRenderer: {cameraLoader.resetActive = true; cameraLoader.resetActive = false}
Component.onCompleted: console.log("Camera completed"+ " ["+index+"]")
Component.onDestruction: console.log("Camera destroyed"+ " ["+index+"]")
Text{
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.margins: 10
elide: Text.ElideRight
maximumLineCount: 1
text: avatarCell.currentDevice.displayName
color: 'white'
}
}
}
Component {
@ -255,79 +274,44 @@ Rectangle {
anchors.fill: parent
//participantDeviceModel: avatarCell.currentDevice
isPreview: true
onRequestNewRenderer: {cameraLoader.resetActive = true}
onRequestNewRenderer: {cameraLoader.resetActive = true; cameraLoader.resetActive = false}
Component.onCompleted: console.log("Preview completed"+ " ["+index+"]")
Component.onDestruction: console.log("Preview destroyed"+ " ["+index+"]")
ActionButton{
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: 15
anchors.topMargin: 15
isCustom: true
colorSet: VideoConferenceStyle.buttons.closePreview
onClicked: grid.remove( index)
}
}
}
}
Rectangle{
anchors.fill: parent
color: avatarCell.currentDevice.isMe ? '#09FF0000' : '#0900FF00'
}
}
OpacityMask{
anchors.fill: parent
source: container
maskSource: showArea
invert:false
visible: conference.callModel
// rotation: 180
}
/*
MouseArea{
anchors.fill: parent
onClicked: {grid.remove( index)}
}
*/
}
}
}
}
/*
GridLayout {
id: grid
Layout.fillHeight: true
Layout.fillWidth: true
Layout.leftMargin: 70
Layout.rightMargin: 70
Layout.topMargin: 15
Layout.bottomMargin: 20
Layout.alignment: Qt.AlignCenter
columns: 3
property int radius : 8
Rectangle{
Layout.fillHeight: true
Layout.fillWidth: true
color: 'red'
radius: parent.radius
}
Rectangle{
Layout.fillHeight: true
Layout.fillWidth: true
color: 'green'
radius: parent.radius
}
Rectangle{
Layout.fillHeight: true
Layout.fillWidth: true
color: 'orange'
radius: parent.radius
}
Rectangle{
Layout.fillHeight: true
Layout.fillWidth: true
color: 'yellow'
radius: parent.radius
}
Rectangle{
Layout.fillHeight: true
Layout.fillWidth: true
Layout.columnSpan: 2
color: 'blue'
radius: parent.radius
}
Rectangle{
Layout.fillHeight: true
Layout.fillWidth: true
color: 'pink'
radius: parent.radius
}
}
*/
// -------------------------------------------------------------------------
// Action Buttons.
// -------------------------------------------------------------------------
@ -355,54 +339,70 @@ Rectangle {
// Action buttons
RowLayout{
Layout.alignment: Qt.AlignCenter
spacing: 10
spacing: 30
RowLayout{
spacing: 10
Row {
spacing: 2
visible: SettingsModel.muteMicrophoneEnabled
property bool microMuted: callModel.microMuted
VuMeter {
enabled: !parent.microMuted
Timer {
interval: 50
repeat: true
running: parent.enabled
onTriggered: parent.value = callModel.microVu
}
}
ActionSwitch {
id: micro
isCustom: true
backgroundRadius: 90
colorSet: enabled ? VideoConferenceStyle.buttons.microOn : VideoConferenceStyle.buttons.microOff
colorSet: parent.microMuted ? VideoConferenceStyle.buttons.microOff : VideoConferenceStyle.buttons.microOn
onClicked: callModel.microMuted = !parent.microMuted
}
}
Row {
spacing: 2
property bool speakerMuted: callModel.speakerMuted
VuMeter {
enabled: !parent.speakerMuted
Timer {
interval: 50
repeat: true
running: parent.enabled
onTriggered: parent.value = callModel.speakerVu
}
}
ActionSwitch {
id: speaker
isCustom: true
backgroundRadius: 90
colorSet: enabled ? VideoConferenceStyle.buttons.speakerOn : VideoConferenceStyle.buttons.speakerOff
colorSet: parent.speakerMuted ? VideoConferenceStyle.buttons.speakerOff : VideoConferenceStyle.buttons.speakerOn
onClicked: callModel.speakerMuted = !parent.speakerMuted
}
}
ActionSwitch {
id: camera
isCustom: true
backgroundRadius: 90
colorSet: conference.callModel && conference.callModel.videoEnabled ? VideoConferenceStyle.buttons.cameraOn : VideoConferenceStyle.buttons.cameraOff
//updating: conference.callModel.videoEnabled && conference.callModel.updating
onClicked: if(conference.callModel) conference.callModel.videoEnabled = !conference.callModel.videoEnabled
colorSet: callModel && callModel.videoEnabled ? VideoConferenceStyle.buttons.cameraOn : VideoConferenceStyle.buttons.cameraOff
updating: callModel.videoEnabled && callModel.updating
onClicked: if(callModel) callModel.videoEnabled = !callModel.videoEnabled
}
}
RowLayout{
spacing: 10
ActionButton{
isCustom: true
backgroundRadius: width/2
colorSet: VideoConferenceStyle.buttons.pause
visible: SettingsModel.callPauseEnabled
updating: callModel.updating
colorSet: callModel.pausedByUser ? VideoConferenceStyle.buttons.play : VideoConferenceStyle.buttons.pause
onClicked: callModel.pausedByUser = !callModel.pausedByUser
}
ActionButton{
isCustom: true
@ -422,6 +422,7 @@ Rectangle {
isCustom: true
backgroundRadius: width/2
colorSet: VideoConferenceStyle.buttons.chat
visible: false // TODO for next version
}
ActionButton{
isCustom: true
@ -434,42 +435,34 @@ Rectangle {
isCustom: true
backgroundRadius: 4
colorSet: VideoConferenceStyle.buttons.callQuality
percentageDisplayed: 0
//onClicked: Logic.openCallStatistics()
// See: http://www.linphone.org/docs/liblinphone/group__call__misc.html#ga62c7d3d08531b0cc634b797e273a0a73
onClicked: {console.log("opening stats");Logic.openCallStatistics();console.log("Stats should be opened")}
Timer {
interval: 500
repeat: true
running: true
triggeredOnStart: true
onTriggered: {
callQuality.percentageDisplayed = (callQuality.percentageDisplayed + 10 ) % 110
/*
// Note: `quality` is in the [0, 5] interval and -1.
var quality = call.quality
var quality = callModel.quality
if(quality >= 0)
callQuality.percentageDisplayed = quality * 100 / 5
else
callQuality.percentageDisplayed = 0
*/
}
}
/*
CallStatistics {
id: callStatistics
call: incall.call
width: container.width
relativeTo: callQuality
call: callModel
width: conference.width
relativeTo: keypadButton
relativeY: CallStyle.header.stats.relativeY
onClosed: Logic.handleCallStatisticsClosed()
}*/
onOpened: console.log("Stats Opened: " +call+", " +width +", "+relativeY)
}
}
ActionButton{
isCustom: true
@ -479,4 +472,14 @@ Rectangle {
}
}
}
// ---------------------------------------------------------------------------
// TelKeypad.
// ---------------------------------------------------------------------------
TelKeypad {
id: telKeypad
call: callModel
visible: SettingsModel.showTelKeypadAutomatically
}
}

View file

@ -12,10 +12,10 @@ import App.Styles 1.0
// =============================================================================
ColumnLayout {
id: container
property int filterMode: ConferenceInfoProxyModel.ConferenceType.Scheduled
id: mainItem
property int filterType: -1
spacing: 0
Component.onCompleted: filterType = ConferenceInfoProxyModel.Scheduled
// ---------------------------------------------------------------------------
// Title
// ---------------------------------------------------------------------------
@ -26,9 +26,9 @@ ColumnLayout {
color: ConferencesStyle.bar.backgroundColor
Text{
anchors.verticalCenter: parent.center
anchors.fill: parent
verticalAlignment: Qt.AlignCenter
verticalAlignment: Qt.AlignVCenter
anchors.leftMargin: 40
text: 'Mes conférences'
@ -54,9 +54,10 @@ ColumnLayout {
'PROGRAMMEES',
'INVITATIONS'
]
selectedButton: mainItem.filterType
onClicked: {
mainItem.filterMode = (button === 0 ? ConferenceInfoProxyModel.ConferenceType.Ended : button === 1 ?ConferenceInfoProxyModel.ConferenceType.Scheduled : ConferenceInfoProxyModel.ConferenceType.Invitations);
mainItem.filterType = (button === 0 ? ConferenceInfoProxyModel.Ended : button === 1 ?ConferenceInfoProxyModel.Scheduled : ConferenceInfoProxyModel.Invitations);
//mainItem.filterType = button
}
}
}
@ -80,12 +81,12 @@ ColumnLayout {
section {
criteria: ViewSection.FullString
delegate: sectionHeading
property: 'date'
property: '$modelKey'
}
model: ConferenceInfoProxyModel{
id: conferencesProxyModel
filterType: mainItem.filterType
}
// -----------------------------------------------------------------------
@ -147,17 +148,18 @@ ColumnLayout {
GridView{
id: calendarGrid
//anchors.fill: parent
cellWidth: (container.width-20)/2
cellWidth: (mainItem.width-20)/2
cellHeight: 100
model: $modelData
height: cellHeight * ( (count+1) /2)
width: container.width - 20
width: mainItem.width - 20
delegate:Rectangle {
id: entry
width: calendarGrid.cellWidth -10
height: calendarGrid.cellHeight -10
radius: 6
color: ConferencesStyle.conference.backgroundColor.normal
color: mainItem.filterType == ConferenceInfoProxyModel.Ended ? ConferencesStyle.conference.backgroundColor.ended
: ConferencesStyle.conference.backgroundColor.scheduled
border.color: calendarMessage.containsMouse ? ConferencesStyle.conference.selectedBorder.color : 'transparent'
border.width: ConferencesStyle.conference.selectedBorder.width
ChatCalendarMessage{
@ -165,6 +167,9 @@ ColumnLayout {
conferenceInfoModel: $modelData
width: calendarGrid.cellWidth
maxWidth: calendarGrid.cellWidth
gotoButtonMode: mainItem.filterType == ConferenceInfoProxyModel.Scheduled ? 1
: mainItem.filterType == ConferenceInfoProxyModel.Ended ? -1
: 0
}
}
}

View file

@ -107,9 +107,18 @@ DialogPlus {
conferenceInfoModel.isScheduled = scheduledSwitch.checked
if( scheduledSwitch.checked){
var startDateTime = new Date()
startDateTime.setDate(dateField.getDate())
startDateTime.setTime(timeField.getTime())
conferenceInfoModel.dateTime = startDateTime
var d = dateField.getDate()
var t = timeField.getTime()
console.log("A " +startDateTime)
startDateTime.setFullYear(d.getFullYear(), d.getMonth(), d.getDate())
console.log("B " +startDateTime)
startDateTime.setHours(t.getHours())
console.log("C " +startDateTime)
startDateTime.setMinutes(t.getMinutes())
console.log("D " +startDateTime)
startDateTime.setSeconds(0)
console.log("E " +startDateTime)
conferenceInfoModel.dateTime = startDateTime
conferenceInfoModel.duration = durationField.text
}
conferenceInfoModel.subject = subject.text

View file

@ -1,4 +1,5 @@
import QtQuick 2.7
import QtGraphicalEffects 1.12
import Common 1.0
import Linphone 1.0
@ -26,10 +27,39 @@ DialogPlus {
Loader{
id: previewLoader
anchors.fill: parent
sourceComponent: CameraPreview {
sourceComponent: Item{
anchors.fill: parent
Rectangle{
id: showArea
anchors.fill: parent
radius: 50
visible:false
color: 'red'
}
Rectangle{
id: test
anchors.fill: parent
visible:false
color: 'green'
}
CameraPreview {
id: camera
anchors.fill: parent
onRequestNewRenderer: previewLoader.active = false
visible: false
}
OpacityMask{
anchors.fill: camera
source: camera
maskSource: showArea
invert:false
visible: true
rotation: 180
}
}
active: true
onActiveChanged: {
console.log("Active changed : " +active)

View file

@ -48,6 +48,18 @@ QtObject {
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'ma_h_b_fg').color
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'ma_p_b_fg').color
}
property QtObject closeButton: QtObject{
property int iconSize: 40
property string name : 'close'
property string icon : 'close_custom'
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_b_n', icon, 'l_n_b_bg').color
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_b_h', icon, 'l_h_b_bg').color
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_b_p', icon, 'l_p_b_bg').color
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_n', icon, 'l_n_b_fg').color
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_h', icon, 'l_h_b_fg').color
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_p', icon, 'l_p_b_fg').color
}
}
property QtObject chat: QtObject {

View file

@ -394,11 +394,21 @@ QtObject {
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_inv_fg').color
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_inv_fg').color
}
//------------------------------------------------------------------------------
property QtObject closePreview: QtObject {
property int iconSize: 40
property string icon : 'close_custom'
property string name : 'close_preview'
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 'me_n_b_inv_bg').color
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 'me_h_b_inv_bg').color
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 'me_p_b_inv_bg').color
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 'me_n_b_inv_fg').color
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_inv_fg').color
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_inv_fg').color
}
//------------------------------------------------------------------------------
property QtObject history: QtObject {
property int iconSize: 40
property string icon : 'history_custom'

View file

@ -35,7 +35,8 @@ QtObject {
property int spacing: 15
property QtObject backgroundColor: QtObject {
property color normal: ColorsList.add(sectionName+'_conference_bg_n', 'conference_bg').color
property color ended: ColorsList.add(sectionName+'_conference_ended_bg', 'conference_bg').color
property color scheduled: ColorsList.add(sectionName+'_conference_scheduled_bg', 'e').color
property color hovered: ColorsList.add(sectionName+'_conference_bg_h', 'g10').color
}

@ -1 +1 @@
Subproject commit 28110434a26de7d9eaec988ce045504d5818e385
Subproject commit 9791a5bc6cdce83db83c11af9b4c0e29bf9805a5