Commit a00a2cbf authored by Ronan's avatar Ronan

feat(ui/views/App/Calls/ConferenceManager): in progress

parent bace15a0
......@@ -106,6 +106,7 @@ set(SOURCES
src/components/codecs/AbstractCodecsModel.cpp
src/components/codecs/AudioCodecsModel.cpp
src/components/codecs/VideoCodecsModel.cpp
src/components/conference/ConferenceAddModel.cpp
src/components/conference/ConferenceHelperModel.cpp
src/components/contact/ContactModel.cpp
src/components/contact/VcardModel.cpp
......@@ -148,6 +149,7 @@ set(HEADERS
src/components/codecs/AudioCodecsModel.hpp
src/components/codecs/VideoCodecsModel.hpp
src/components/Components.hpp
src/components/conference/ConferenceAddModel.hpp
src/components/conference/ConferenceHelperModel.hpp
src/components/contact/ContactModel.hpp
src/components/contact/VcardModel.hpp
......
......@@ -342,7 +342,6 @@
<file>ui/views/App/Calls/AbstractStartingCall.qml</file>
<file>ui/views/App/Calls/CallsWindow.js</file>
<file>ui/views/App/Calls/CallsWindow.qml</file>
<file>ui/views/App/Calls/ConferenceManager.js</file>
<file>ui/views/App/Calls/ConferenceManager.qml</file>
<file>ui/views/App/Calls/EndedCall.qml</file>
<file>ui/views/App/Calls/IncallFullscreenWindow.qml</file>
......
......@@ -359,6 +359,7 @@ void App::registerTypes () {
registerMetaType<ChatModel::EntryType>("ChatModel::EntryType");
registerUncreatableType(CallModel, "CallModel");
registerUncreatableType(ConferenceAddModel, "ConferenceAddModel");
registerUncreatableType(ContactModel, "ContactModel");
registerUncreatableType(SipAddressObserver, "SipAddressObserver");
registerUncreatableType(VcardModel, "VcardModel");
......
......@@ -31,6 +31,7 @@
#include "chat/ChatProxyModel.hpp"
#include "codecs/AudioCodecsModel.hpp"
#include "codecs/VideoCodecsModel.hpp"
#include "conference/ConferenceAddModel.hpp"
#include "conference/ConferenceHelperModel.hpp"
#include "contacts/ContactsListProxyModel.hpp"
#include "core/CoreManager.hpp"
......
/*
* ConferenceAddModel.cpp
* Copyright (C) 2017 Belledonne Communications, Grenoble, France
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Created on: May 18, 2017
* Author: Ronan Abhamon
*/
#include "../../Utils.hpp"
#include "../core/CoreManager.hpp"
#include "ConferenceHelperModel.hpp"
#include "ConferenceAddModel.hpp"
using namespace std;
// =============================================================================
ConferenceAddModel::ConferenceAddModel (QObject *parent) : QAbstractListModel(parent) {
mConferenceHelperModel = qobject_cast<ConferenceHelperModel *>(parent);
Q_ASSERT(mConferenceHelperModel != nullptr);
for (auto &participant : CoreManager::getInstance()->getCore()->getConference()->getParticipants())
addToConference(participant);
}
int ConferenceAddModel::rowCount (const QModelIndex &) const {
return mRefs.count();
}
QHash<int, QByteArray> ConferenceAddModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$sipAddress";
return roles;
}
QVariant ConferenceAddModel::data (const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mRefs.count())
return QVariant();
if (role == Qt::DisplayRole)
return QVariant::fromValue(*mRefs[row]);
return QVariant();
}
// -----------------------------------------------------------------------------
bool ConferenceAddModel::addToConference (const QString &sipAddress) {
if (mSipAddresses.contains(sipAddress))
return false;
int row = rowCount();
beginInsertRows(QModelIndex(), row, row);
qInfo() << QStringLiteral("Add sip address to conference: `%1`.").arg(sipAddress);
shared_ptr<linphone::Address> linphoneAddress = CoreManager::getInstance()->getCore()->interpretUrl(
::Utils::qStringToLinphoneString(sipAddress)
);
addToConference(linphoneAddress);
endInsertRows();
mConferenceHelperModel->invalidate();
return true;
}
bool ConferenceAddModel::removeFromConference (const QString &sipAddress) {
auto it = mSipAddresses.find(sipAddress);
if (it == mSipAddresses.end())
return false;
int row = mRefs.indexOf(&(*it));
beginRemoveRows(QModelIndex(), row, row);
qInfo() << QStringLiteral("Remove sip address from conference: `%1`.").arg(sipAddress);
mRefs.removeAt(row);
mSipAddresses.remove(sipAddress);
endRemoveRows();
mConferenceHelperModel->invalidate();
return true;
}
// -----------------------------------------------------------------------------
void ConferenceAddModel::addToConference (const std::shared_ptr<linphone::Address> &linphoneAddress) {
QString sipAddress = ::Utils::linphoneStringToQString(linphoneAddress->asStringUriOnly());
QVariantMap map;
map["sipAddress"] = sipAddress;
map["__linphoneAddress"] = QVariant::fromValue(linphoneAddress);
mSipAddresses[sipAddress] = map;
mRefs << &mSipAddresses[sipAddress];
}
/*
* ConferenceAddModel.hpp
* Copyright (C) 2017 Belledonne Communications, Grenoble, France
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Created on: May 18, 2017
* Author: Ronan Abhamon
*/
#ifndef CONFERENCE_ADD_MODEL_H_
#define CONFERENCE_ADD_MODEL_H_
#include <memory>
#include <QAbstractListModel>
// =============================================================================
class ConferenceHelperModel;
namespace linphone {
class Address;
}
class ConferenceAddModel : public QAbstractListModel {
Q_OBJECT;
public:
ConferenceAddModel (QObject *parent = Q_NULLPTR);
~ConferenceAddModel () = default;
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 bool addToConference (const QString &sipAddress);
Q_INVOKABLE bool removeFromConference (const QString &sipAddress);
bool contains (const QString &sipAddress) const {
return mSipAddresses.contains(sipAddress);
}
private:
void addToConference (const std::shared_ptr<linphone::Address> &linphoneAddress);
QHash<QString, QVariantMap> mSipAddresses;
QList<const QVariantMap *> mRefs;
ConferenceHelperModel *mConferenceHelperModel;
};
Q_DECLARE_METATYPE(std::shared_ptr<linphone::Address> );
#endif // CONFERENCE_ADD_MODEL_H_
......@@ -20,24 +20,26 @@
* Author: Ronan Abhamon
*/
#include "../../Utils.hpp"
#include "../../app/App.hpp"
#include "../core/CoreManager.hpp"
#include "../sip-addresses/SipAddressesProxyModel.hpp"
#include "ConferenceAddModel.hpp"
#include "ConferenceHelperModel.hpp"
using namespace std;
// =============================================================================
ConferenceHelperModel::ConferenceHelperModel (QObject *parent) : QSortFilterProxyModel(parent) {
CoreManager *coreManager = CoreManager::getInstance();
for (const auto &participant : coreManager->getCore()->getConference()->getParticipants())
mInConference << ::Utils::linphoneStringToQString(participant->asStringUriOnly());
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
CallsListModel *calls = coreManager->getCallsListModel();
mConference = core->getConference();
if (!mConference)
mConference = core->createConferenceWithParams(core->createConferenceParams());
QObject::connect(calls, &CallsListModel::rowsAboutToBeRemoved, this, &ConferenceHelperModel::handleCallsAboutToBeRemoved);
QObject::connect(calls, &CallsListModel::callRunning, this, &ConferenceHelperModel::handleCallRunning);
mConferenceAddModel = new ConferenceAddModel(this);
App::getInstance()->getEngine()->setObjectOwnership(mConferenceAddModel, QQmlEngine::CppOwnership);
setSourceModel(new SipAddressesProxyModel(this));
}
......@@ -59,57 +61,6 @@ void ConferenceHelperModel::setFilter (const QString &pattern) {
bool ConferenceHelperModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const {
const QModelIndex &index = sourceModel()->index(sourceRow, 0, sourceParent);
const QVariantMap &data = index.data().toMap();
const QString &sipAddress = data["sipAddress"].toString();
return !mInConference.contains(sipAddress) && !mToAdd.contains(sipAddress);
}
// -----------------------------------------------------------------------------
void ConferenceHelperModel::handleCallsAboutToBeRemoved (const QModelIndex &, int first, int last) {
CallsListModel *calls = CoreManager::getInstance()->getCallsListModel();
bool soFarSoGood = false;
for (int i = first; i <= last; ++i) {
const CallModel *callModel = calls->data(calls->index(first, 0)).value<CallModel *>();
const QString &sipAddress = callModel->getSipAddress();
if (removeFromConference(sipAddress))
soFarSoGood = true;
}
if (soFarSoGood) {
invalidateFilter();
emit inConferenceChanged(mInConference);
}
}
void ConferenceHelperModel::handleCallRunning (int, CallModel *callModel) {
const QString &sipAddress = callModel->getSipAddress();
bool soFarSoGood = callModel->getCall()->getConference()
? addToConference(sipAddress)
: removeFromConference(sipAddress);
if (soFarSoGood) {
invalidateFilter();
emit inConferenceChanged(mInConference);
}
}
// -----------------------------------------------------------------------------
bool ConferenceHelperModel::addToConference (const QString &sipAddress) {
bool ret = !mInConference.contains(sipAddress);
if (ret) {
qInfo() << QStringLiteral("Add sip address to conference: `%1`.").arg(sipAddress);
mInConference << sipAddress;
}
return ret;
}
bool ConferenceHelperModel::removeFromConference (const QString &sipAddress) {
bool ret = mInConference.removeOne(sipAddress);
if (ret)
qInfo() << QStringLiteral("Remove sip address from conference: `%1`.").arg(sipAddress);
return ret;
return !mConferenceAddModel->contains(data["sipAddress"].toString());
}
......@@ -20,16 +20,26 @@
* Author: Ronan Abhamon
*/
#ifndef CONFERENCE_HELPER_MODEL_H_
#define CONFERENCE_HELPER_MODEL_H_
#include <memory>
#include <QSortFilterProxyModel>
// =============================================================================
class CallModel;
class ConferenceAddModel;
namespace linphone {
class Conference;
}
class ConferenceHelperModel : public QSortFilterProxyModel {
Q_OBJECT;
Q_PROPERTY(QStringList inConference READ getInConference NOTIFY inConferenceChanged);
Q_PROPERTY(ConferenceAddModel * toAdd READ getConferenceAddModel CONSTANT);
public:
ConferenceHelperModel (QObject *parent = Q_NULLPTR);
......@@ -37,25 +47,21 @@ public:
QHash<int, QByteArray> roleNames () const override;
Q_INVOKABLE void setFilter (const QString &pattern);
void update ();
signals:
void inConferenceChanged (const QStringList &inConference);
Q_INVOKABLE void setFilter (const QString &pattern);
protected:
bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
private:
void handleCallRunning (int index, CallModel *callModel);
void handleCallsAboutToBeRemoved (const QModelIndex &parent, int first, int last);
bool addToConference (const QString &sipAddress);
bool removeFromConference (const QString &sipAddress);
QStringList getInConference () {
return mInConference;
ConferenceAddModel *getConferenceAddModel () const {
return mConferenceAddModel;
}
QStringList mInConference;
QStringList mToAdd;
ConferenceAddModel *mConferenceAddModel;
std::shared_ptr<linphone::Conference> mConference;
};
#endif // CONFERENCE_HELPER_MODEL_H_
......@@ -66,6 +66,8 @@ SearchBox {
genSipAddress: searchBar.filter
model: SipAddressesProxyModel {}
onEntryClicked: {
searchBar.closeMenu()
searchBar.entryClicked(entry)
......
......@@ -260,10 +260,4 @@ ScrollableListView {
}
}
}
// ---------------------------------------------------------------------------
// Model.
// ---------------------------------------------------------------------------
model: SipAddressesProxyModel {}
}
// =============================================================================
// `ConferenceManager.qml` Logic.
// =============================================================================
function updateFilter (text) {
console.log('TODO')
}
......@@ -6,8 +6,6 @@ import Linphone 1.0
import App.Styles 1.0
import 'ConferenceManager.js' as Logic
// =============================================================================
ConfirmDialog {
......@@ -46,7 +44,7 @@ ConfirmDialog {
icon: 'search'
onTextChanged: Logic.updateFilter(text)
onTextChanged: conferenceHelperModel.setFilter(text)
}
ScrollableListViewField {
......@@ -54,22 +52,22 @@ ConfirmDialog {
Layout.fillWidth: true
SipAddressesView {
id: view
anchors.fill: parent
actions: [{
icon: 'video_call',
icon: 'video_call', // TODO: replace me.
handler: function (entry) {
console.log('toto')
conferenceHelperModel.toAdd.addToConference(entry.sipAddress)
}
}]
genSipAddress: filter.text
onEntryClicked: {
console.log('todo2')
model: ConferenceHelperModel {
id: conferenceHelperModel
}
onEntryClicked: actions[0].handler(entry)
}
}
}
......@@ -93,9 +91,22 @@ ConfirmDialog {
// -------------------------------------------------------------------------
ScrollableListViewField {
Layout.topMargin: filter.height + ConferenceManagerStyle.columns.selector.spacing
Layout.fillHeight: true
Layout.fillWidth: true
Layout.topMargin: filter.height + ConferenceManagerStyle.columns.selector.spacing
SipAddressesView {
anchors.fill: parent
actions: [{
icon: 'video_call', // TODO: replace me.
handler: function (entry) {
model.removeFromConference(entry.sipAddress)
}
}]
model: conferenceHelperModel.toAdd
}
}
}
}
linphone @ 1e113618
Subproject commit 84441343adedad0007a05b438abe04a7c105c6ca
Subproject commit 1e113618275ba4ab8bcadb8cbbd6c641045d8d41
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment