From a00a2cbf4d465ba52a35fb807b41c0a23e934946 Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Thu, 18 May 2017 16:44:53 +0200 Subject: [PATCH] feat(ui/views/App/Calls/ConferenceManager): in progress --- linphone-desktop/CMakeLists.txt | 2 + linphone-desktop/resources.qrc | 1 - linphone-desktop/src/app/App.cpp | 1 + .../src/components/Components.hpp | 1 + .../conference/ConferenceAddModel.cpp | 118 ++++++++++++++++++ .../conference/ConferenceAddModel.hpp | 68 ++++++++++ .../conference/ConferenceHelperModel.cpp | 71 ++--------- .../conference/ConferenceHelperModel.hpp | 34 ++--- .../SmartSearchBar/SmartSearchBar.qml | 2 + .../Linphone/View/SipAddressesView.qml | 6 - .../ui/views/App/Calls/ConferenceManager.js | 7 -- .../ui/views/App/Calls/ConferenceManager.qml | 31 +++-- submodules/linphone | 2 +- 13 files changed, 245 insertions(+), 99 deletions(-) create mode 100644 linphone-desktop/src/components/conference/ConferenceAddModel.cpp create mode 100644 linphone-desktop/src/components/conference/ConferenceAddModel.hpp delete mode 100644 linphone-desktop/ui/views/App/Calls/ConferenceManager.js diff --git a/linphone-desktop/CMakeLists.txt b/linphone-desktop/CMakeLists.txt index c296d1d24..8b2fe8317 100644 --- a/linphone-desktop/CMakeLists.txt +++ b/linphone-desktop/CMakeLists.txt @@ -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 diff --git a/linphone-desktop/resources.qrc b/linphone-desktop/resources.qrc index 324a7aa96..6f7876a2a 100644 --- a/linphone-desktop/resources.qrc +++ b/linphone-desktop/resources.qrc @@ -342,7 +342,6 @@ ui/views/App/Calls/AbstractStartingCall.qml ui/views/App/Calls/CallsWindow.js ui/views/App/Calls/CallsWindow.qml - ui/views/App/Calls/ConferenceManager.js ui/views/App/Calls/ConferenceManager.qml ui/views/App/Calls/EndedCall.qml ui/views/App/Calls/IncallFullscreenWindow.qml diff --git a/linphone-desktop/src/app/App.cpp b/linphone-desktop/src/app/App.cpp index 54b99f7a2..125bd0b75 100644 --- a/linphone-desktop/src/app/App.cpp +++ b/linphone-desktop/src/app/App.cpp @@ -359,6 +359,7 @@ void App::registerTypes () { registerMetaType("ChatModel::EntryType"); registerUncreatableType(CallModel, "CallModel"); + registerUncreatableType(ConferenceAddModel, "ConferenceAddModel"); registerUncreatableType(ContactModel, "ContactModel"); registerUncreatableType(SipAddressObserver, "SipAddressObserver"); registerUncreatableType(VcardModel, "VcardModel"); diff --git a/linphone-desktop/src/components/Components.hpp b/linphone-desktop/src/components/Components.hpp index fea615669..1f7189641 100644 --- a/linphone-desktop/src/components/Components.hpp +++ b/linphone-desktop/src/components/Components.hpp @@ -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" diff --git a/linphone-desktop/src/components/conference/ConferenceAddModel.cpp b/linphone-desktop/src/components/conference/ConferenceAddModel.cpp new file mode 100644 index 000000000..f4406ae6d --- /dev/null +++ b/linphone-desktop/src/components/conference/ConferenceAddModel.cpp @@ -0,0 +1,118 @@ +/* + * 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(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 ConferenceAddModel::roleNames () const { + QHash 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 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 &linphoneAddress) { + QString sipAddress = ::Utils::linphoneStringToQString(linphoneAddress->asStringUriOnly()); + QVariantMap map; + + map["sipAddress"] = sipAddress; + map["__linphoneAddress"] = QVariant::fromValue(linphoneAddress); + + mSipAddresses[sipAddress] = map; + mRefs << &mSipAddresses[sipAddress]; +} diff --git a/linphone-desktop/src/components/conference/ConferenceAddModel.hpp b/linphone-desktop/src/components/conference/ConferenceAddModel.hpp new file mode 100644 index 000000000..55b73dcfc --- /dev/null +++ b/linphone-desktop/src/components/conference/ConferenceAddModel.hpp @@ -0,0 +1,68 @@ +/* + * 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 + +#include + +// ============================================================================= + +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 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 &linphoneAddress); + + QHash mSipAddresses; + QList mRefs; + + ConferenceHelperModel *mConferenceHelperModel; +}; + +Q_DECLARE_METATYPE(std::shared_ptr ); + +#endif // CONFERENCE_ADD_MODEL_H_ diff --git a/linphone-desktop/src/components/conference/ConferenceHelperModel.cpp b/linphone-desktop/src/components/conference/ConferenceHelperModel.cpp index 4871af27a..4ca7f49fe 100644 --- a/linphone-desktop/src/components/conference/ConferenceHelperModel.cpp +++ b/linphone-desktop/src/components/conference/ConferenceHelperModel.cpp @@ -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(); + shared_ptr core = CoreManager::getInstance()->getCore(); - for (const auto &participant : coreManager->getCore()->getConference()->getParticipants()) - mInConference << ::Utils::linphoneStringToQString(participant->asStringUriOnly()); + mConference = core->getConference(); + if (!mConference) + mConference = core->createConferenceWithParams(core->createConferenceParams()); - CallsListModel *calls = coreManager->getCallsListModel(); - - 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(); - 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()); } diff --git a/linphone-desktop/src/components/conference/ConferenceHelperModel.hpp b/linphone-desktop/src/components/conference/ConferenceHelperModel.hpp index f69728fda..e5e231ac6 100644 --- a/linphone-desktop/src/components/conference/ConferenceHelperModel.hpp +++ b/linphone-desktop/src/components/conference/ConferenceHelperModel.hpp @@ -20,16 +20,26 @@ * Author: Ronan Abhamon */ +#ifndef CONFERENCE_HELPER_MODEL_H_ +#define CONFERENCE_HELPER_MODEL_H_ + +#include + #include // ============================================================================= 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 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 mConference; }; + +#endif // CONFERENCE_HELPER_MODEL_H_ diff --git a/linphone-desktop/ui/modules/Linphone/SmartSearchBar/SmartSearchBar.qml b/linphone-desktop/ui/modules/Linphone/SmartSearchBar/SmartSearchBar.qml index 30de38a72..c2f22a4c7 100644 --- a/linphone-desktop/ui/modules/Linphone/SmartSearchBar/SmartSearchBar.qml +++ b/linphone-desktop/ui/modules/Linphone/SmartSearchBar/SmartSearchBar.qml @@ -66,6 +66,8 @@ SearchBox { genSipAddress: searchBar.filter + model: SipAddressesProxyModel {} + onEntryClicked: { searchBar.closeMenu() searchBar.entryClicked(entry) diff --git a/linphone-desktop/ui/modules/Linphone/View/SipAddressesView.qml b/linphone-desktop/ui/modules/Linphone/View/SipAddressesView.qml index 4bf7f134b..6860a64cb 100644 --- a/linphone-desktop/ui/modules/Linphone/View/SipAddressesView.qml +++ b/linphone-desktop/ui/modules/Linphone/View/SipAddressesView.qml @@ -260,10 +260,4 @@ ScrollableListView { } } } - - // --------------------------------------------------------------------------- - // Model. - // --------------------------------------------------------------------------- - - model: SipAddressesProxyModel {} } diff --git a/linphone-desktop/ui/views/App/Calls/ConferenceManager.js b/linphone-desktop/ui/views/App/Calls/ConferenceManager.js deleted file mode 100644 index 55ec1fc06..000000000 --- a/linphone-desktop/ui/views/App/Calls/ConferenceManager.js +++ /dev/null @@ -1,7 +0,0 @@ -// ============================================================================= -// `ConferenceManager.qml` Logic. -// ============================================================================= - -function updateFilter (text) { - console.log('TODO') -} diff --git a/linphone-desktop/ui/views/App/Calls/ConferenceManager.qml b/linphone-desktop/ui/views/App/Calls/ConferenceManager.qml index 954d60d11..243ed7da0 100644 --- a/linphone-desktop/ui/views/App/Calls/ConferenceManager.qml +++ b/linphone-desktop/ui/views/App/Calls/ConferenceManager.qml @@ -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 + } } } } diff --git a/submodules/linphone b/submodules/linphone index 84441343a..1e1136182 160000 --- a/submodules/linphone +++ b/submodules/linphone @@ -1 +1 @@ -Subproject commit 84441343adedad0007a05b438abe04a7c105c6ca +Subproject commit 1e113618275ba4ab8bcadb8cbbd6c641045d8d41