diff --git a/submodules/belcard b/submodules/belcard
index f5a8603f8..ebd037585 160000
--- a/submodules/belcard
+++ b/submodules/belcard
@@ -1 +1 @@
-Subproject commit f5a8603f8e379486d3a4bfa4d74861b0a2d880dd
+Subproject commit ebd037585965ce80f01be5290abc7e5455009eb8
diff --git a/submodules/belle-sip b/submodules/belle-sip
index b8bc7f2a5..b1695fb52 160000
--- a/submodules/belle-sip
+++ b/submodules/belle-sip
@@ -1 +1 @@
-Subproject commit b8bc7f2a5a899e8acfa59c7b49ebabcbab7d0efd
+Subproject commit b1695fb52ede996ed0b50167aab787d1373f49e4
diff --git a/submodules/linphone b/submodules/linphone
index 030b1c05d..758d516a3 160000
--- a/submodules/linphone
+++ b/submodules/linphone
@@ -1 +1 @@
-Subproject commit 030b1c05d5d77dac2d34a1be1c98516a8fb9887a
+Subproject commit 758d516a39ce3ee484e185a6e1a2653659f6fd81
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 524b6d670..36eaa4fa0 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -13,6 +13,7 @@ set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CUSTOM_FLAGS "\
+-Wall \
-Wcast-align \
-Wconversion \
-Werror=suggest-override \
@@ -58,6 +59,8 @@ set(SOURCES
src/app/Paths.cpp
src/app/ThumbnailProvider.cpp
src/components/camera/Camera.cpp
+ src/components/call/CallModel.cpp
+ src/components/calls/CallsListModel.cpp
src/components/chat/ChatModel.cpp
src/components/chat/ChatProxyModel.cpp
src/components/contact/ContactObserver.cpp
@@ -84,6 +87,8 @@ set(HEADERS
src/app/Paths.hpp
src/app/ThumbnailProvider.hpp
src/components/camera/Camera.hpp
+ src/components/call/CallModel.hpp
+ src/components/calls/CallsListModel.hpp
src/components/chat/ChatModel.hpp
src/components/chat/ChatProxyModel.hpp
src/components/contact/ContactObserver.hpp
@@ -103,9 +108,7 @@ set(HEADERS
src/utils.hpp
)
-set(QRC_RESOURCES
- resources.qrc
-)
+set(QRC_RESOURCES resources.qrc)
set(LANGUAGES_DIRECTORY assets/languages)
set(I18N_FILENAME i18n.qrc)
diff --git a/tests/assets/images/burger_menu_hovered.svg b/tests/assets/images/burger_menu_hovered.svg
new file mode 100644
index 000000000..20270f076
--- /dev/null
+++ b/tests/assets/images/burger_menu_hovered.svg
@@ -0,0 +1,14 @@
+
+
\ No newline at end of file
diff --git a/tests/assets/images/burger_menu_light_hovered.svg b/tests/assets/images/burger_menu_light_hovered.svg
new file mode 100644
index 000000000..fad7b30a8
--- /dev/null
+++ b/tests/assets/images/burger_menu_light_hovered.svg
@@ -0,0 +1,14 @@
+
+
\ No newline at end of file
diff --git a/tests/assets/images/burger_menu_light_normal.svg b/tests/assets/images/burger_menu_light_normal.svg
new file mode 100644
index 000000000..937b1d880
--- /dev/null
+++ b/tests/assets/images/burger_menu_light_normal.svg
@@ -0,0 +1,14 @@
+
+
\ No newline at end of file
diff --git a/tests/assets/images/burger_menu_light_pressed.svg b/tests/assets/images/burger_menu_light_pressed.svg
new file mode 100644
index 000000000..937b1d880
--- /dev/null
+++ b/tests/assets/images/burger_menu_light_pressed.svg
@@ -0,0 +1,14 @@
+
+
\ No newline at end of file
diff --git a/tests/assets/images/burger_menu_normal.svg b/tests/assets/images/burger_menu_normal.svg
new file mode 100644
index 000000000..937b1d880
--- /dev/null
+++ b/tests/assets/images/burger_menu_normal.svg
@@ -0,0 +1,14 @@
+
+
\ No newline at end of file
diff --git a/tests/assets/images/burger_menu_pressed.svg b/tests/assets/images/burger_menu_pressed.svg
new file mode 100644
index 000000000..937b1d880
--- /dev/null
+++ b/tests/assets/images/burger_menu_pressed.svg
@@ -0,0 +1,14 @@
+
+
\ No newline at end of file
diff --git a/tests/assets/images/call_sign_connected.svg b/tests/assets/images/call_sign_connected.svg
new file mode 100644
index 000000000..fa89999c6
--- /dev/null
+++ b/tests/assets/images/call_sign_connected.svg
@@ -0,0 +1,13 @@
+
+
\ No newline at end of file
diff --git a/tests/assets/images/call_sign_incoming.svg b/tests/assets/images/call_sign_incoming.svg
new file mode 100644
index 000000000..7c3595e57
--- /dev/null
+++ b/tests/assets/images/call_sign_incoming.svg
@@ -0,0 +1,13 @@
+
+
\ No newline at end of file
diff --git a/tests/assets/images/call_sign_outgoing.svg b/tests/assets/images/call_sign_outgoing.svg
new file mode 100644
index 000000000..e30a239d6
--- /dev/null
+++ b/tests/assets/images/call_sign_outgoing.svg
@@ -0,0 +1,13 @@
+
+
\ No newline at end of file
diff --git a/tests/assets/images/call_sign_paused.svg b/tests/assets/images/call_sign_paused.svg
new file mode 100644
index 000000000..6173dfcd5
--- /dev/null
+++ b/tests/assets/images/call_sign_paused.svg
@@ -0,0 +1,13 @@
+
+
\ No newline at end of file
diff --git a/tests/assets/languages/en.ts b/tests/assets/languages/en.ts
index 308fad2f1..edc62bce0 100644
--- a/tests/assets/languages/en.ts
+++ b/tests/assets/languages/en.ts
@@ -11,17 +11,9 @@
contactsEntry
Contacts
-
- acceptAudioCall
-
-
-
- acceptVideoCall
-
-
hangup
- End call
+ End call
@@ -34,6 +26,30 @@
newConference
NEW CONFERENCE
+
+ acceptAudioCall
+ ACCEPT AUDIO CALL
+
+
+ acceptVideoCall
+ ACCEPT VIDEO CALL
+
+
+ terminateCall
+ HANGUP
+
+
+ resumeCall
+
+
+
+ transferCall
+
+
+
+ pauseCall
+
+
Chat
diff --git a/tests/assets/languages/fr.ts b/tests/assets/languages/fr.ts
index dcef4df81..612bdf29b 100644
--- a/tests/assets/languages/fr.ts
+++ b/tests/assets/languages/fr.ts
@@ -3,17 +3,9 @@
CallControls
-
- acceptAudioCall
-
-
-
- acceptVideoCall
-
-
hangup
- Fin d'appel
+ Fin d'appel
@@ -26,6 +18,30 @@
newConference
NOUVELLE CONFERENCE
+
+ acceptAudioCall
+ ACCEPTER APPEL AUDIO
+
+
+ acceptVideoCall
+ ACCEPTER APPEL VIDEO
+
+
+ terminateCall
+ RACCROCHER
+
+
+ resumeCall
+
+
+
+ transferCall
+
+
+
+ pauseCall
+
+
Chat
diff --git a/tests/resources.qrc b/tests/resources.qrc
index 715908917..398691972 100644
--- a/tests/resources.qrc
+++ b/tests/resources.qrc
@@ -9,6 +9,12 @@
assets/images/attachment_normal.svg
assets/images/attachment_pressed.svg
assets/images/auto_answer.svg
+ assets/images/burger_menu_hovered.svg
+ assets/images/burger_menu_light_hovered.svg
+ assets/images/burger_menu_light_normal.svg
+ assets/images/burger_menu_light_pressed.svg
+ assets/images/burger_menu_normal.svg
+ assets/images/burger_menu_pressed.svg
assets/images/call_accept_hovered.svg
assets/images/call_accept_normal.svg
assets/images/call_accept_pressed.svg
@@ -19,6 +25,10 @@
assets/images/call_quality_1.svg
assets/images/call_quality_2.svg
assets/images/call_quality_3.svg
+ assets/images/call_sign_connected.svg
+ assets/images/call_sign_incoming.svg
+ assets/images/call_sign_outgoing.svg
+ assets/images/call_sign_paused.svg
assets/images/camera_off_hovered.svg
assets/images/camera_off_normal.svg
assets/images/camera_off_pressed.svg
@@ -200,11 +210,8 @@
ui/modules/Common/Tooltip/Tooltip.qml
ui/modules/Common/View/ScrollableListView.qml
ui/modules/Linphone/Account/AccountStatus.qml
- ui/modules/Linphone/Call/CallControls.qml
- ui/modules/Linphone/Call/ConnectedCallsControl.qml
- ui/modules/Linphone/Call/IncomingCallControls.qml
- ui/modules/Linphone/Call/OutgoingCallControls.qml
- ui/modules/Linphone/Call/PausedCallControls.qml
+ ui/modules/Linphone/Calls/CallControls.qml
+ ui/modules/Linphone/Calls/Calls.qml
ui/modules/Linphone/Chat/Chat.qml
ui/modules/Linphone/Chat/Event.qml
ui/modules/Linphone/Chat/FileMessage.qml
@@ -223,6 +230,8 @@
ui/modules/Linphone/qmldir
ui/modules/Linphone/SmartSearchBar.qml
ui/modules/Linphone/Styles/Account/AccountStatusStyle.qml
+ ui/modules/Linphone/Styles/Calls/CallControlsStyle.qml
+ ui/modules/Linphone/Styles/Calls/CallsStyle.qml
ui/modules/Linphone/Styles/ChatStyle.qml
ui/modules/Linphone/Styles/Contact/AvatarStyle.qml
ui/modules/Linphone/Styles/Contact/ContactDescriptionStyle.qml
diff --git a/tests/src/app/App.cpp b/tests/src/app/App.cpp
index 10e01f9ca..3479084c3 100644
--- a/tests/src/app/App.cpp
+++ b/tests/src/app/App.cpp
@@ -4,14 +4,15 @@
#include
#include
+#include "../components/calls/CallsListModel.hpp"
#include "../components/camera/Camera.hpp"
#include "../components/chat/ChatProxyModel.hpp"
#include "../components/contacts/ContactsListProxyModel.hpp"
#include "../components/core/CoreManager.hpp"
#include "../components/settings/AccountSettingsModel.hpp"
#include "../components/settings/SettingsModel.hpp"
-#include "../components/timeline/TimelineModel.hpp"
#include "../components/smart-search-bar/SmartSearchBarModel.hpp"
+#include "../components/timeline/TimelineModel.hpp"
#include "App.hpp"
@@ -96,17 +97,20 @@ void App::initContentApp () {
void App::registerTypes () {
qInfo() << "Registering types...";
+ qmlRegisterUncreatableType(
+ "Linphone", 1, 0, "CallModel", "CallModel is uncreatable."
+ );
qmlRegisterUncreatableType(
- "Linphone", 1, 0, "ContactModel", "ContactModel is uncreatable"
+ "Linphone", 1, 0, "ContactModel", "ContactModel is uncreatable."
);
qmlRegisterUncreatableType(
- "Linphone", 1, 0, "ContactObserver", "ContactObserver is uncreatable"
- );
- qmlRegisterUncreatableType(
- "Linphone", 1, 0, "VcardModel", "VcardModel is uncreatable"
+ "Linphone", 1, 0, "ContactObserver", "ContactObserver is uncreatable."
);
qmlRegisterUncreatableType(
- "Linphone", 1, 0, "Presence", "Presence is uncreatable"
+ "Linphone", 1, 0, "Presence", "Presence is uncreatable."
+ );
+ qmlRegisterUncreatableType(
+ "Linphone", 1, 0, "VcardModel", "VcardModel is uncreatable."
);
qmlRegisterSingletonType(
@@ -123,20 +127,6 @@ void App::registerTypes () {
}
);
- qmlRegisterSingletonType(
- "Linphone", 1, 0, "ContactsListModel",
- [](QQmlEngine *, QJSEngine *) -> QObject *{
- return CoreManager::getInstance()->getContactsListModel();
- }
- );
-
- qmlRegisterSingletonType(
- "Linphone", 1, 0, "SipAddressesModel",
- [](QQmlEngine *, QJSEngine *) -> QObject *{
- return CoreManager::getInstance()->getSipAddressesModel();
- }
- );
-
qmlRegisterSingletonType(
"Linphone", 1, 0, "AccountSettingsModel",
[](QQmlEngine *, QJSEngine *) -> QObject *{
@@ -144,6 +134,20 @@ void App::registerTypes () {
}
);
+ qmlRegisterSingletonType(
+ "Linphone", 1, 0, "CallsListModel",
+ [](QQmlEngine *, QJSEngine *) -> QObject *{
+ return new CallsListModel();
+ }
+ );
+
+ qmlRegisterSingletonType(
+ "Linphone", 1, 0, "ContactsListModel",
+ [](QQmlEngine *, QJSEngine *) -> QObject *{
+ return CoreManager::getInstance()->getContactsListModel();
+ }
+ );
+
qmlRegisterSingletonType(
"Linphone", 1, 0, "SettingsModel",
[](QQmlEngine *, QJSEngine *) -> QObject *{
@@ -151,6 +155,13 @@ void App::registerTypes () {
}
);
+ qmlRegisterSingletonType(
+ "Linphone", 1, 0, "SipAddressesModel",
+ [](QQmlEngine *, QJSEngine *) -> QObject *{
+ return CoreManager::getInstance()->getSipAddressesModel();
+ }
+ );
+
qmlRegisterSingletonType(
"Linphone", 1, 0, "TimelineModel",
[](QQmlEngine *, QJSEngine *) -> QObject *{
diff --git a/tests/src/components/call/CallModel.cpp b/tests/src/components/call/CallModel.cpp
new file mode 100644
index 000000000..b701e9c7c
--- /dev/null
+++ b/tests/src/components/call/CallModel.cpp
@@ -0,0 +1,71 @@
+#include "../../utils.hpp"
+#include "../core/CoreManager.hpp"
+
+#include "CallModel.hpp"
+
+// =============================================================================
+
+CallModel::CallModel (shared_ptr linphone_call) {
+ m_linphone_call = linphone_call;
+}
+
+// -----------------------------------------------------------------------------
+
+void CallModel::acceptAudioCall () {
+ CoreManager::getInstance()->getCore()->acceptCall(m_linphone_call);
+}
+
+void CallModel::terminateCall () {
+ CoreManager::getInstance()->getCore()->terminateCall(m_linphone_call);
+}
+
+// -----------------------------------------------------------------------------
+
+QString CallModel::getSipAddress () const {
+ return ::Utils::linphoneStringToQString(m_linphone_call->getRemoteAddress()->asStringUriOnly());
+}
+
+CallModel::CallStatus CallModel::getStatus () const {
+ switch (m_linphone_call->getState()) {
+ case linphone::CallStateConnected:
+ case linphone::CallStateStreamsRunning:
+ return CallStatusConnected;
+
+ case linphone::CallStateEnd:
+ case linphone::CallStateError:
+ case linphone::CallStateRefered:
+ case linphone::CallStateReleased:
+ return CallStatusEnded;
+
+ case linphone::CallStatePaused:
+ case linphone::CallStatePausedByRemote:
+ return CallStatusPaused;
+
+ default:
+ break;
+ }
+
+ return m_linphone_call->getDir() == linphone::CallDirIncoming ? CallStatusIncoming : CallStatusOutgoing;
+}
+
+bool CallModel::getPausedByUser () const {
+ return m_linphone_call->getState() == linphone::CallStatePaused;
+}
+
+void CallModel::setPausedByUser (bool status) {
+ bool paused = getPausedByUser();
+
+ if (status) {
+ if (!paused) {
+ CoreManager::getInstance()->getCore()->pauseCall(m_linphone_call);
+ emit pausedByUserChanged(true);
+ }
+
+ return;
+ }
+
+ if (paused) {
+ CoreManager::getInstance()->getCore()->resumeCall(m_linphone_call);
+ emit pausedByUserChanged(false);
+ }
+}
diff --git a/tests/src/components/call/CallModel.hpp b/tests/src/components/call/CallModel.hpp
new file mode 100644
index 000000000..3f3f67ce8
--- /dev/null
+++ b/tests/src/components/call/CallModel.hpp
@@ -0,0 +1,55 @@
+#ifndef CALL_MODEL_H_
+#define CALL_MODEL_H_
+
+#include
+#include
+
+// =============================================================================
+
+class CallModel : public QObject {
+ Q_OBJECT;
+
+ Q_PROPERTY(QString sipAddress READ getSipAddress CONSTANT);
+
+ Q_PROPERTY(CallStatus status READ getStatus NOTIFY statusChanged);
+ Q_PROPERTY(bool isOutgoing READ isOutgoing CONSTANT);
+
+ Q_PROPERTY(bool pausedByUser READ getPausedByUser WRITE setPausedByUser NOTIFY pausedByUserChanged);
+
+public:
+ enum CallStatus {
+ CallStatusConnected,
+ CallStatusEnded,
+ CallStatusIncoming,
+ CallStatusOutgoing,
+ CallStatusPaused
+ };
+
+ Q_ENUM(CallStatus);
+
+ CallModel (std::shared_ptr linphone_call);
+ ~CallModel () = default;
+
+ Q_INVOKABLE void acceptAudioCall ();
+ Q_INVOKABLE void terminateCall ();
+
+signals:
+ void statusChanged (CallStatus status);
+ void pausedByUserChanged (bool status);
+
+private:
+ QString getSipAddress () const;
+
+ CallStatus getStatus () const;
+
+ bool isOutgoing () const {
+ return m_linphone_call->getDir() == linphone::CallDirOutgoing;
+ }
+
+ bool getPausedByUser () const;
+ void setPausedByUser (bool status);
+
+ std::shared_ptr m_linphone_call;
+};
+
+#endif // CALL_MODEL_H_
diff --git a/tests/src/components/calls/CallsListModel.cpp b/tests/src/components/calls/CallsListModel.cpp
new file mode 100644
index 000000000..782b68138
--- /dev/null
+++ b/tests/src/components/calls/CallsListModel.cpp
@@ -0,0 +1,103 @@
+#include
+
+#include "../../app/App.hpp"
+#include "../core/CoreManager.hpp"
+
+#include "CallsListModel.hpp"
+
+using namespace std;
+
+// =============================================================================
+
+CallsListModel::CallsListModel (QObject *parent) : QAbstractListModel(parent) {
+ m_core_handlers = CoreManager::getInstance()->getHandlers();
+ QObject::connect(
+ &(*m_core_handlers), &CoreHandlers::callStateChanged,
+ this, [this](const shared_ptr &linphone_call, linphone::CallState state) {
+ switch (state) {
+ case linphone::CallStateIncomingReceived:
+ addCall(linphone_call);
+ break;
+ case linphone::CallStateOutgoingInit:
+ addCall(linphone_call);
+ break;
+ case linphone::CallStateEnd:
+ case linphone::CallStateError:
+ removeCall(linphone_call);
+ break;
+ default:
+
+ break;
+ }
+ }
+ );
+}
+
+int CallsListModel::rowCount (const QModelIndex &) const {
+ return m_list.count();
+}
+
+QHash CallsListModel::roleNames () const {
+ QHash roles;
+ roles[Qt::DisplayRole] = "$call";
+ return roles;
+}
+
+QVariant CallsListModel::data (const QModelIndex &index, int role) const {
+ int row = index.row();
+
+ if (!index.isValid() || row < 0 || row >= m_list.count())
+ return QVariant();
+
+ if (role == Qt::DisplayRole)
+ return QVariant::fromValue(m_list[row]);
+
+ return QVariant();
+}
+
+// -----------------------------------------------------------------------------
+
+bool CallsListModel::removeRow (int row, const QModelIndex &parent) {
+ return removeRows(row, 1, parent);
+}
+
+bool CallsListModel::removeRows (int row, int count, const QModelIndex &parent) {
+ int limit = row + count - 1;
+
+ if (row < 0 || count < 0 || limit >= m_list.count())
+ return false;
+
+ beginRemoveRows(parent, row, limit);
+
+ for (int i = 0; i < count; ++i)
+ m_list.takeAt(row)->deleteLater();
+
+ endRemoveRows();
+
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+
+void CallsListModel::addCall (const shared_ptr &linphone_call) {
+ CallModel *call = new CallModel(linphone_call);
+ App::getInstance()->getEngine()->setObjectOwnership(call, QQmlEngine::CppOwnership);
+ linphone_call->setData("call-model", *call);
+
+ int row = rowCount();
+
+ beginInsertRows(QModelIndex(), row, row);
+ m_list << call;
+ endInsertRows();
+}
+
+void CallsListModel::removeCall (const shared_ptr &linphone_call) {
+ CallModel &call = linphone_call->getData("call-model");
+ linphone_call->unsetData("call-model");
+
+ qInfo() << "Removing call:" << &call;
+
+ int index = m_list.indexOf(&call);
+ if (index == -1 || !removeRow(index))
+ qWarning() << "Unable to remove call:" << &call;
+}
diff --git a/tests/src/components/calls/CallsListModel.hpp b/tests/src/components/calls/CallsListModel.hpp
new file mode 100644
index 000000000..daf9ef5d7
--- /dev/null
+++ b/tests/src/components/calls/CallsListModel.hpp
@@ -0,0 +1,36 @@
+#ifndef CALLS_LIST_MODEL_H_
+#define CALLS_LIST_MODEL_H_
+
+#include
+
+#include "../call/CallModel.hpp"
+
+// =============================================================================
+
+class CoreHandlers;
+
+class CallsListModel : public QAbstractListModel {
+ Q_OBJECT;
+
+public:
+ CallsListModel (QObject *parent = Q_NULLPTR);
+ ~CallsListModel () = default;
+
+ int rowCount (const QModelIndex &index = QModelIndex()) const override;
+
+ QHash roleNames () const override;
+ QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+private:
+ bool removeRow (int row, const QModelIndex &parent = QModelIndex());
+ bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
+
+ void addCall (const std::shared_ptr &linphone_call);
+ void removeCall (const std::shared_ptr &linphone_call);
+
+ QList m_list;
+
+ std::shared_ptr m_core_handlers;
+};
+
+#endif // CALLS_LIST_MODEL_H_
diff --git a/tests/src/components/contacts/ContactsListModel.cpp b/tests/src/components/contacts/ContactsListModel.cpp
index c9360edba..1771ed0bd 100644
--- a/tests/src/components/contacts/ContactsListModel.cpp
+++ b/tests/src/components/contacts/ContactsListModel.cpp
@@ -111,6 +111,8 @@ void ContactsListModel::removeContact (ContactModel *contact) {
qWarning() << "Unable to remove contact:" << contact;
}
+// -----------------------------------------------------------------------------
+
void ContactsListModel::addContact (ContactModel *contact) {
QObject::connect(
contact, &ContactModel::contactUpdated,
diff --git a/tests/src/components/core/CoreHandlers.cpp b/tests/src/components/core/CoreHandlers.cpp
index d7e8a13dc..552361f0c 100644
--- a/tests/src/components/core/CoreHandlers.cpp
+++ b/tests/src/components/core/CoreHandlers.cpp
@@ -10,8 +10,8 @@ using namespace std;
// =============================================================================
void CoreHandlers::onAuthenticationRequested (
- const std::shared_ptr &,
- const std::shared_ptr &,
+ const shared_ptr &,
+ const shared_ptr &,
linphone::AuthMethod
) {
qDebug() << "Auth request";
@@ -19,11 +19,11 @@ void CoreHandlers::onAuthenticationRequested (
void CoreHandlers::onCallStateChanged (
const shared_ptr &,
- const shared_ptr &,
- linphone::CallState,
+ const shared_ptr &call,
+ linphone::CallState state,
const string &
) {
- qDebug() << "call";
+ emit callStateChanged(call, state);
}
void CoreHandlers::onMessageReceived (
diff --git a/tests/src/components/core/CoreHandlers.hpp b/tests/src/components/core/CoreHandlers.hpp
index d1bb63cde..55b03146b 100644
--- a/tests/src/components/core/CoreHandlers.hpp
+++ b/tests/src/components/core/CoreHandlers.hpp
@@ -12,6 +12,7 @@ class CoreHandlers :
Q_OBJECT;
signals:
+ void callStateChanged (const std::shared_ptr &call, linphone::CallState state);
void messageReceived (const std::shared_ptr &message);
private:
@@ -24,7 +25,7 @@ private:
void onCallStateChanged (
const std::shared_ptr &core,
const std::shared_ptr &call,
- linphone::CallState cstate,
+ linphone::CallState state,
const std::string &message
) override;
diff --git a/tests/src/components/notifier/Notifier.cpp b/tests/src/components/notifier/Notifier.cpp
index 8f4363006..99ef0b681 100644
--- a/tests/src/components/notifier/Notifier.cpp
+++ b/tests/src/components/notifier/Notifier.cpp
@@ -152,8 +152,8 @@ void Notifier::showNotification (QObject *notification, int timeout) {
void Notifier::notifyReceivedMessage (
int timeout,
- const std::shared_ptr &room,
- const std::shared_ptr &message
+ const shared_ptr &room,
+ const shared_ptr &message
) {
QObject *object = createNotification(Notifier::MessageReceived);
diff --git a/tests/src/components/sip-addresses/SipAddressesModel.cpp b/tests/src/components/sip-addresses/SipAddressesModel.cpp
index 6474adcac..22f2c5b6d 100644
--- a/tests/src/components/sip-addresses/SipAddressesModel.cpp
+++ b/tests/src/components/sip-addresses/SipAddressesModel.cpp
@@ -19,10 +19,10 @@ SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(pare
QObject::connect(contacts, &ContactsListModel::contactAdded, this, &SipAddressesModel::handleContactAdded);
QObject::connect(contacts, &ContactsListModel::contactRemoved, this, &SipAddressesModel::handleContactRemoved);
- m_handlers = CoreManager::getInstance()->getHandlers();
+ m_core_handlers = CoreManager::getInstance()->getHandlers();
QObject::connect(
- &(*m_handlers), &CoreHandlers::messageReceived,
- this, [this](const std::shared_ptr &message) {
+ &(*m_core_handlers), &CoreHandlers::messageReceived,
+ this, [this](const shared_ptr &message) {
const QString &sip_address = ::Utils::linphoneStringToQString(message->getFromAddress()->asStringUriOnly());
addOrUpdateSipAddress(sip_address, nullptr, message);
}
@@ -107,7 +107,7 @@ void SipAddressesModel::connectToChatModel (ChatModel *chat_model) {
for (auto &signal : { &ChatModel::messageSent, &ChatModel::messageReceived }) {
QObject::connect(
chat_model, signal,
- this, [this](const std::shared_ptr &message) {
+ this, [this](const shared_ptr &message) {
addOrUpdateSipAddress(
::Utils::linphoneStringToQString(message->getToAddress()->asStringUriOnly()), nullptr, message
);
diff --git a/tests/src/components/sip-addresses/SipAddressesModel.hpp b/tests/src/components/sip-addresses/SipAddressesModel.hpp
index d1f2716aa..eeecd655f 100644
--- a/tests/src/components/sip-addresses/SipAddressesModel.hpp
+++ b/tests/src/components/sip-addresses/SipAddressesModel.hpp
@@ -60,7 +60,7 @@ private:
QMultiHash m_observers;
- std::shared_ptr m_handlers;
+ std::shared_ptr m_core_handlers;
};
#endif // SIP_ADDRESSES_MODEL_H_
diff --git a/tests/ui/modules/Common/Menu/ActionMenuEntry.qml b/tests/ui/modules/Common/Menu/ActionMenuEntry.qml
index f5b787ee9..1c09ca0c5 100644
--- a/tests/ui/modules/Common/Menu/ActionMenuEntry.qml
+++ b/tests/ui/modules/Common/Menu/ActionMenuEntry.qml
@@ -33,6 +33,7 @@ Rectangle {
color: ActionMenuStyle.entry.text.color
elide: Text.ElideRight
font.pointSize: ActionMenuStyle.entry.text.fontSize
+
height: parent.height
verticalAlignment: Text.AlignVCenter
}
@@ -43,6 +44,6 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
- onClicked: entry.clicked
+ onClicked: entry.clicked()
}
}
diff --git a/tests/ui/modules/Common/Styles/Menu/ActionMenuStyle.qml b/tests/ui/modules/Common/Styles/Menu/ActionMenuStyle.qml
index a2dd626ac..3aa9585cf 100644
--- a/tests/ui/modules/Common/Styles/Menu/ActionMenuStyle.qml
+++ b/tests/ui/modules/Common/Styles/Menu/ActionMenuStyle.qml
@@ -9,18 +9,18 @@ QtObject {
property int spacing: 1
property QtObject entry: QtObject {
- property int leftMargin: 4
- property int rightMargin: 4
+ property int leftMargin: 18
+ property int rightMargin: 8
property QtObject color: QtObject {
- property color hovered: Colors.s
- property color normal: Colors.i
- property color pressed: Colors.t
+ property color hovered: Colors.j
+ property color normal: Colors.g
+ property color pressed: Colors.i
}
property QtObject text: QtObject {
property color color: Colors.k
- property int fontSize: 8
+ property int fontSize: 9
}
}
}
diff --git a/tests/ui/modules/Linphone/Call/CallControls.qml b/tests/ui/modules/Linphone/Call/CallControls.qml
deleted file mode 100644
index b7fe94842..000000000
--- a/tests/ui/modules/Linphone/Call/CallControls.qml
+++ /dev/null
@@ -1,91 +0,0 @@
-import QtQuick 2.7
-import QtQuick.Layouts 1.3
-import QtQuick.Controls 2.0
-
-import Linphone 1.0
-import Common 1.0
-
-// ===================================================================
-
-RowLayout {
- property string sipAddress
-
- // TODO.
- property var contact: ContactsListModel.mapSipAddressTocd (
- sipAddress
- )
-
- implicitHeight: contact.height
- spacing: 1
-
- Rectangle {
- Layout.fillWidth: true
- color: '#434343'
- implicitHeight: _contact.height
-
- Contact {
- id: contact
-
- anchors.fill: parent
- sipAddressColor: '#FFFFFF'
- usernameColor: '#FFFFFF'
- }
- }
-
- Rectangle {
- id: button
-
- Layout.preferredHeight: contact.height
- Layout.preferredWidth: 42
- color: menu.isOpen() ? '#FE5E00' : '#434343'
-
- Text {
- anchors.centerIn: parent
- color: '#FFFFFF'
- text: '...'
- }
-
- MouseArea {
- anchors.fill: parent
- hoverEnabled: true
-
- onClicked: {
- menu.showMenu()
- }
- }
- }
-
- DropDownMenu {
- id: menu
-
- implicitWidth: actionMenu.width
- launcher: button
- relativeTo: button
- relativeX: button.width + 1
-
- ActionMenu {
- id: actionMenu
-
- entryHeight: 22
- entryWidth: 120
-
- ActionMenuEntry {
- entryName: qsTr('acceptAudioCall')
-
- onClicked: menu.hideMenu()
- }
-
- ActionMenuEntry {
- entryName: qsTr('acceptVideoCall')
-
- onClicked: menu.hideMenu()
- }
-
- ActionMenuEntry {
- entryName: qsTr('hangup')
-
- onClicked: menu.hideMenu()
- }
- }
- }
-}
diff --git a/tests/ui/modules/Linphone/Call/ConnectedCallsControl.qml b/tests/ui/modules/Linphone/Call/ConnectedCallsControl.qml
deleted file mode 100644
index 1ba758f7f..000000000
--- a/tests/ui/modules/Linphone/Call/ConnectedCallsControl.qml
+++ /dev/null
@@ -1,3 +0,0 @@
-import QtQuick 2.7
-
-Item {}
diff --git a/tests/ui/modules/Linphone/Call/IncomingCallControls.qml b/tests/ui/modules/Linphone/Call/IncomingCallControls.qml
deleted file mode 100644
index 1ba758f7f..000000000
--- a/tests/ui/modules/Linphone/Call/IncomingCallControls.qml
+++ /dev/null
@@ -1,3 +0,0 @@
-import QtQuick 2.7
-
-Item {}
diff --git a/tests/ui/modules/Linphone/Call/OutgoingCallControls.qml b/tests/ui/modules/Linphone/Call/OutgoingCallControls.qml
deleted file mode 100644
index 1ba758f7f..000000000
--- a/tests/ui/modules/Linphone/Call/OutgoingCallControls.qml
+++ /dev/null
@@ -1,3 +0,0 @@
-import QtQuick 2.7
-
-Item {}
diff --git a/tests/ui/modules/Linphone/Call/PausedCallControls.qml b/tests/ui/modules/Linphone/Call/PausedCallControls.qml
deleted file mode 100644
index 1ba758f7f..000000000
--- a/tests/ui/modules/Linphone/Call/PausedCallControls.qml
+++ /dev/null
@@ -1,3 +0,0 @@
-import QtQuick 2.7
-
-Item {}
diff --git a/tests/ui/modules/Linphone/Calls/CallControls.qml b/tests/ui/modules/Linphone/Calls/CallControls.qml
new file mode 100644
index 000000000..e7474f393
--- /dev/null
+++ b/tests/ui/modules/Linphone/Calls/CallControls.qml
@@ -0,0 +1,74 @@
+import QtQuick 2.7
+import QtQuick.Layouts 1.3
+
+import Common 1.0
+import Linphone 1.0
+import Linphone.Styles 1.0
+
+// =============================================================================
+
+Rectangle {
+ id: callControls
+
+ // ---------------------------------------------------------------------------
+
+ default property alias _content: content.data
+
+ property alias signIcon: signIcon.icon
+ property alias sipAddressColor: contact.sipAddressColor
+ property alias usernameColor: contact.usernameColor
+ property string sipAddress
+
+ // ---------------------------------------------------------------------------
+
+ property var _contactObserver: SipAddressesModel.getContactObserver(sipAddress)
+
+ // ---------------------------------------------------------------------------
+
+ color: CallControlsStyle.color
+ height: CallControlsStyle.height
+ width: CallControlsStyle.width
+
+ RowLayout {
+ anchors {
+ fill: parent
+ leftMargin: CallControlsStyle.leftMargin
+ rightMargin: CallControlsStyle.rightMargin
+ }
+
+ spacing: 0
+
+ Contact {
+ id: contact
+
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ anchors.fill: parent
+
+ displayUnreadMessagesCount: true
+
+ entry: ({
+ contact: _contactObserver.contact,
+ sipAddress: callControls.sipAddress
+ })
+ }
+
+ Item {
+ id: content
+ Layout.fillHeight: true
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+
+ Icon {
+ id: signIcon
+
+ anchors {
+ left: parent.left
+ top: parent.top
+ }
+
+ iconSize: CallControlsStyle.signSize
+ }
+}
diff --git a/tests/ui/modules/Linphone/Calls/Calls.qml b/tests/ui/modules/Linphone/Calls/Calls.qml
new file mode 100644
index 000000000..7a2780c03
--- /dev/null
+++ b/tests/ui/modules/Linphone/Calls/Calls.qml
@@ -0,0 +1,172 @@
+import QtQuick 2.7
+
+import Common 1.0
+import Linphone 1.0
+import Linphone.Styles 1.0
+
+// =============================================================================
+
+ListView {
+ id: calls
+
+ property var _mapStatusToParams
+
+ // ---------------------------------------------------------------------------
+
+ function _getSignIcon (call) {
+ if (call) {
+ var string = _mapStatusToParams[call.status].string
+ return string ? 'call_sign_' + string : ''
+ }
+
+ return ''
+ }
+
+ function _getParams (call) {
+ if (call) {
+ return _mapStatusToParams[call.status]
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+
+ boundsBehavior: Flickable.StopAtBounds
+ clip: true
+ spacing: 0
+
+ // ---------------------------------------------------------------------------
+
+ Component.onCompleted: {
+ _mapStatusToParams = {}
+
+ _mapStatusToParams[CallModel.CallStatusConnected] = {
+ actions: [{
+ name: qsTr('resumeCall'),
+ handler: (function (call) { call.pausedByUser = false })
+ }, {
+ name: qsTr('transferCall'),
+ handler: (function (call) { call.transferCall() })
+ }, {
+ name: qsTr('terminateCall'),
+ handler: (function (call) { call.terminateCall() })
+ }],
+ component: callActions,
+ string: 'connected'
+ }
+
+ _mapStatusToParams[CallModel.CallStatusEnded] = {}
+
+ _mapStatusToParams[CallModel.CallStatusIncoming] = {
+ actions: [{
+ name: qsTr('acceptAudioCall'),
+ handler: (function (call) { call.acceptAudioCall() })
+ }, {
+ name: qsTr('acceptVideoCall'),
+ handler: (function (call) { call.acceptVideoCall() })
+ }, {
+ name: qsTr('terminateCall'),
+ handler: (function (call) { call.terminateCall() })
+ }],
+ component: callActions,
+ string: 'incoming'
+ }
+
+ _mapStatusToParams[CallModel.CallStatusOutgoing] = {
+ component: callAction,
+ handler: (function (call) { call.terminateCall() }),
+ icon: 'hangup',
+ string: 'outgoing'
+ }
+
+ _mapStatusToParams[CallModel.CallStatusPaused] = {
+ actions: [{
+ name: qsTr('pauseCall'),
+ handler: (function (call) { call.pausedByUser = true })
+ }, {
+ name: qsTr('transferCall'),
+ handler: (function (call) { call.transferCall() })
+ }, {
+ name: qsTr('terminateCall'),
+ handler: (function (call) { call.terminateCall() })
+ }],
+ component: callActions,
+ string: 'paused'
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+
+ Component {
+ id: callAction
+
+ ActionButton {
+ icon: params.icon
+ iconSize: CallsStyle.entry.iconActionSize
+
+ onClicked: params.handler(call)
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+
+ Component {
+ id: callActions
+
+ ActionButton {
+ id: button
+
+ icon: 'burger_menu'
+ iconSize: CallsStyle.entry.iconMenuSize
+
+ onClicked: menu.showMenu()
+
+ DropDownMenu {
+ id: menu
+
+ implicitWidth: actionMenu.width
+ launcher: button
+ relativeTo: callControls
+ relativeX: callControls.width
+
+ ActionMenu {
+ id: actionMenu
+
+ entryHeight: CallsStyle.entry.height
+ entryWidth: CallsStyle.entry.width
+
+ Repeater {
+ model: params.actions
+
+ ActionMenuEntry {
+ entryName: modelData.name
+
+ onClicked: {
+ menu.hideMenu()
+ params.actions[index].handler(call)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+
+ delegate: CallControls {
+ id: _callControls
+
+ signIcon: _getSignIcon($call)
+ sipAddress: $call.sipAddress
+ width: parent.width
+
+ Loader {
+ property var call: $call
+ property var callControls: _callControls
+ property var params: _getParams($call)
+
+ anchors.centerIn: parent
+ sourceComponent: params.component
+ }
+ }
+}
diff --git a/tests/ui/modules/Linphone/SmartSearchBar.qml b/tests/ui/modules/Linphone/SmartSearchBar.qml
index 014c00016..9e55bdf11 100644
--- a/tests/ui/modules/Linphone/SmartSearchBar.qml
+++ b/tests/ui/modules/Linphone/SmartSearchBar.qml
@@ -77,7 +77,7 @@ SearchBox {
Layout.fillHeight: true
Layout.fillWidth: true
- entry: Object ({
+ entry: ({
sipAddress: interpretableSipAddress
})
}
diff --git a/tests/ui/modules/Linphone/Styles/Calls/CallControlsStyle.qml b/tests/ui/modules/Linphone/Styles/Calls/CallControlsStyle.qml
new file mode 100644
index 000000000..60516875a
--- /dev/null
+++ b/tests/ui/modules/Linphone/Styles/Calls/CallControlsStyle.qml
@@ -0,0 +1,15 @@
+pragma Singleton
+import QtQuick 2.7
+
+import Common 1.0
+
+// =============================================================================
+
+QtObject {
+ property color color: Colors.e
+ property int height: 60
+ property int leftMargin: 12
+ property int rightMargin: 12
+ property int signSize: 40
+ property int width: 240
+}
diff --git a/tests/ui/modules/Linphone/Styles/Calls/CallsStyle.qml b/tests/ui/modules/Linphone/Styles/Calls/CallsStyle.qml
new file mode 100644
index 000000000..24b9115f4
--- /dev/null
+++ b/tests/ui/modules/Linphone/Styles/Calls/CallsStyle.qml
@@ -0,0 +1,15 @@
+pragma Singleton
+import QtQuick 2.7
+
+import Common 1.0
+
+// =============================================================================
+
+QtObject {
+ property QtObject entry: QtObject {
+ property int iconActionSize: 30
+ property int iconMenuSize: 17
+ property int height: 30
+ property int width: 200
+ }
+}
diff --git a/tests/ui/modules/Linphone/Styles/qmldir b/tests/ui/modules/Linphone/Styles/qmldir
index 9b23e21cf..0975f56a2 100644
--- a/tests/ui/modules/Linphone/Styles/qmldir
+++ b/tests/ui/modules/Linphone/Styles/qmldir
@@ -8,6 +8,9 @@ singleton AccountStatusStyle 1.0 Account/AccountStatusStyle.qml
singleton ChatStyle 1.0 ChatStyle.qml
+singleton CallsStyle 1.0 Calls/CallsStyle.qml
+singleton CallControlsStyle 1.0 Calls/CallControlsStyle.qml
+
singleton AvatarStyle 1.0 Contact/AvatarStyle.qml
singleton ContactDescriptionStyle 1.0 Contact/ContactDescriptionStyle.qml
singleton ContactStyle 1.0 Contact/ContactStyle.qml
diff --git a/tests/ui/modules/Linphone/qmldir b/tests/ui/modules/Linphone/qmldir
index 1c3b0321d..d89a4ba52 100644
--- a/tests/ui/modules/Linphone/qmldir
+++ b/tests/ui/modules/Linphone/qmldir
@@ -9,8 +9,8 @@ module Linphone
# Account
AccountStatus 1.0 Account/AccountStatus.qml
-# Call
-CallControls 1.0 Call/CallControls.qml
+# Calls
+Calls 1.0 Calls/Calls.qml
# Chat
Chat 1.0 Chat/Chat.qml
diff --git a/tests/ui/views/App/Calls/Calls.qml b/tests/ui/views/App/Calls/Calls.qml
index db72c322a..58f31cd1e 100644
--- a/tests/ui/views/App/Calls/Calls.qml
+++ b/tests/ui/views/App/Calls/Calls.qml
@@ -9,11 +9,25 @@ import Linphone 1.0
import App.Styles 1.0
-// ===================================================================
+// =============================================================================
Window {
id: window
+ // ---------------------------------------------------------------------------
+
+ function launchAudioCall (sipAddress) {
+ window.show()
+
+ }
+
+ function launchVideoCall (sipAddress) {
+ window.show()
+
+ }
+
+ // ---------------------------------------------------------------------------
+
minimumHeight: 480
minimumWidth: 960
@@ -33,6 +47,7 @@ Window {
ColumnLayout {
anchors.fill: parent
+ spacing: 0
Item {
Layout.fillWidth: true
@@ -69,52 +84,15 @@ Window {
}
}
- ListView {
- Layout.fillWidth: true
+ Calls {
Layout.fillHeight: true
- spacing: 0
+ Layout.fillWidth: true
+
+ model: CallsListModel
}
}
}
- /* childA: ColumnLayout { */
- /* anchors.fill: parent */
- /* spacing: 0 */
-
- /* Rectangle { */
- /* Layout.fillWidth: true */
- /* Layout.preferredHeight: 50 */
- /* color: '#FFFFFF' */
-
- /* ActionBar { */
- /* anchors.verticalCenter: parent.verticalCenter */
- /* anchors.leftMargin: 10 */
- /* anchors.left: parent.left */
- /* iconSize: 30 */
- /* spacing: 16 */
-
- /* ActionButton { */
- /* icon: 'call' */
- /* } */
-
- /* ActionButton { */
- /* icon: 'conference' */
- /* } */
- /* } */
- /* } */
-
- /* ScrollableListView { */
- /* Layout.fillWidth: true */
- /* Layout.fillHeight: true */
- /* spacing: 1 */
- /* delegate: CallControls { */
- /* width: parent.width */
- /* } */
-
- /* model: callsList */
- /* } */
- /* } */
-
// ---------------------------------------------------------------
// Content.
// ---------------------------------------------------------------
diff --git a/tests/ui/views/App/MainWindow/Contacts.qml b/tests/ui/views/App/MainWindow/Contacts.qml
index cbd91938f..dadfe78d2 100644
--- a/tests/ui/views/App/MainWindow/Contacts.qml
+++ b/tests/ui/views/App/MainWindow/Contacts.qml
@@ -131,12 +131,12 @@ ColumnLayout {
ActionButton {
icon: 'video_call'
- onClicked: CallsWindow.show()
+ onClicked: CallsWindow.launchVideoCall($contact.vcard.sipAddresses[0]) // FIXME: Display menu if many addresses.
}
ActionButton {
icon: 'call'
- onClicked: CallsWindow.show()
+ onClicked: CallsWindow.launchAudioCall($contact.vcard.sipAddresses[0]) // FIXME: Display menu if many addresses.
}
ActionButton {
diff --git a/tests/ui/views/App/MainWindow/Conversation.qml b/tests/ui/views/App/MainWindow/Conversation.qml
index 193f6a330..878f7c4b6 100644
--- a/tests/ui/views/App/MainWindow/Conversation.qml
+++ b/tests/ui/views/App/MainWindow/Conversation.qml
@@ -15,9 +15,7 @@ ColumnLayout {
property string sipAddress
- property var _contact: SipAddressesModel.mapSipAddressToContact(
- sipAddress
- ) || sipAddress
+ property var _contact: SipAddressesModel.mapSipAddressToContact(sipAddress)
function _removeAllEntries () {
Utils.openConfirmDialog(window, {
@@ -57,9 +55,9 @@ ColumnLayout {
Layout.preferredHeight: ConversationStyle.bar.avatarSize
Layout.preferredWidth: ConversationStyle.bar.avatarSize
- image: _contact.vcard ? _contact.vcard.avatar : ''
- presenceLevel: _contact.presenceLevel || -1
- username: LinphoneUtils.getContactUsername(_contact)
+ image: _contact ? _contact.vcard.avatar : ''
+ presenceLevel: _contact ? _contact.presenceLevel : -1
+ username: LinphoneUtils.getContactUsername(_contact || conversation.sipAddress)
}
ContactDescription {
@@ -81,12 +79,12 @@ ColumnLayout {
ActionButton {
icon: 'video_call'
- onClicked: CallsWindow.show()
+ onClicked: CallsWindow.launchVideoCall(conversation.sipAddress)
}
ActionButton {
icon: 'call'
- onClicked: CallsWindow.show()
+ onClicked: CallsWindow.launchAudioCall(conversation.sipAddress)
}
}
@@ -94,7 +92,7 @@ ColumnLayout {
anchors.verticalCenter: parent.verticalCenter
ActionButton {
- icon: Utils.isString(_contact) ? 'contact_add' : 'contact_edit'
+ icon: _contact ? 'contact_add' : 'contact_edit'
iconSize: ConversationStyle.bar.actions.edit.iconSize
onClicked: window.setView('ContactEdit', {
diff --git a/tests/ui/views/App/MainWindow/MainWindow.qml b/tests/ui/views/App/MainWindow/MainWindow.qml
index c6a6a3a78..95a04d84e 100644
--- a/tests/ui/views/App/MainWindow/MainWindow.qml
+++ b/tests/ui/views/App/MainWindow/MainWindow.qml
@@ -159,14 +159,15 @@ ApplicationWindow {
sipAddress: sipAddress
})
}
- onLaunchCall: CallsWindow.show()
+
+ onLaunchCall: CallsWindow.launchAudioCall(sipAddress)
onLaunchChat: {
window.ensureCollapsed()
window.setView('Conversation', {
sipAddress: sipAddress
})
}
- onLaunchVideoCall: CallsWindow.show()
+ onLaunchVideoCall: CallsWindow.launchVideoCall(sipAddress)
onEntryClicked: {
window.ensureCollapsed()