diff --git a/submodules/belcard b/submodules/belcard index 633e151d8..eaeab2d66 160000 --- a/submodules/belcard +++ b/submodules/belcard @@ -1 +1 @@ -Subproject commit 633e151d8a1775e8b4f717158d12bc0c0957c4ed +Subproject commit eaeab2d665423e1fdbf2f59c2ae8da6c3c89c8fa diff --git a/submodules/linphone b/submodules/linphone index 7b70508d9..e816a335c 160000 --- a/submodules/linphone +++ b/submodules/linphone @@ -1 +1 @@ -Subproject commit 7b70508d9591c794ec42a80438a11f067f665994 +Subproject commit e816a335cd1693cdbbde27a69143e1570058ed5f diff --git a/tests/src/components/contact/VcardModel.cpp b/tests/src/components/contact/VcardModel.cpp index 3b7305d6d..0ec6d8700 100644 --- a/tests/src/components/contact/VcardModel.cpp +++ b/tests/src/components/contact/VcardModel.cpp @@ -65,12 +65,12 @@ QString VcardModel::getAvatar () const { ); } -void VcardModel::setAvatar (const QString &path) { +bool VcardModel::setAvatar (const QString &path) { // 1. Try to copy photo in avatars folder. QFile file(path); if (!file.exists() || QImageReader::imageFormat(path).size() == 0) - return; + return false; QFileInfo info(file); QString uuid = QUuid::createUuid().toString(); @@ -81,7 +81,7 @@ void VcardModel::setAvatar (const QString &path) { QString dest = ::Utils::linphoneStringToQString(Database::getAvatarsPath()) + file_id; if (!file.copy(dest)) - return; + return false; qInfo() << QStringLiteral("Update avatar of `%1`. (path=%2)").arg(getUsername()).arg(dest); @@ -112,9 +112,12 @@ void VcardModel::setAvatar (const QString &path) { shared_ptr photo = belcard::BelCardGeneric::create(); photo->setValue(VCARD_SCHEME + ::Utils::qStringToLinphoneString(file_id)); - belcard->addPhoto(photo); + + if (!belcard->addPhoto(photo)) + return false; emit vcardUpdated(); + return true; } // ----------------------------------------------------------------------------- @@ -135,7 +138,7 @@ QVariantMap VcardModel::getAddress () const { return map; } -void VcardModel::setAddress (const QVariantMap &address) { +bool VcardModel::setAddress (const QVariantMap &address) { shared_ptr belcard = m_vcard->getBelcard(); list > addresses = belcard->getAddresses(); @@ -150,9 +153,11 @@ void VcardModel::setAddress (const QVariantMap &address) { belcard_address->setPostalCode(::Utils::qStringToLinphoneString(address["postalCode"].toString())); belcard_address->setCountry(::Utils::qStringToLinphoneString(address["country"].toString())); - belcard->addAddress(belcard_address); + if (!belcard->addAddress(belcard_address)) + return false; emit vcardUpdated(); + return true; } QVariantList VcardModel::getSipAddresses () const { @@ -165,11 +170,19 @@ QVariantList VcardModel::getSipAddresses () const { } bool VcardModel::addSipAddress (const QString &sip_address) { + shared_ptr address = CoreManager::getInstance()->getCore()->createAddress( + ::Utils::qStringToLinphoneString(sip_address) + ); + + if (!address) { + qWarning() << QStringLiteral("Unable to add invalid sip address: `%1`.").arg(sip_address); + return false; + } + qInfo() << QStringLiteral("Add new sip address: `%1`.").arg(sip_address); - m_vcard->addSipAddress(::Utils::qStringToLinphoneString(sip_address)); + m_vcard->addSipAddress(address->asStringUriOnly()); emit vcardUpdated(); - return true; } @@ -227,10 +240,11 @@ bool VcardModel::addCompany (const QString &company) { value->setValue(::Utils::qStringToLinphoneString(company)); qInfo() << QStringLiteral("Add new company: `%1`.").arg(company); - belcard->addRole(value); + + if (!belcard->addRole(value)) + return false; emit vcardUpdated(); - return true; } @@ -276,10 +290,11 @@ bool VcardModel::addEmail (const QString &email) { value->setValue(::Utils::qStringToLinphoneString(email)); qInfo() << QStringLiteral("Add new email: `%1`.").arg(email); - belcard->addEmail(value); + + if (!belcard->addEmail(value)) + return false; emit vcardUpdated(); - return true; } @@ -324,10 +339,11 @@ bool VcardModel::addUrl (const QString &url) { value->setValue(::Utils::qStringToLinphoneString(url)); qInfo() << QStringLiteral("Add new url: `%1`.").arg(url); - belcard->addURL(value); + + if (!belcard->addURL(value)) + return false; emit vcardUpdated(); - return true; } diff --git a/tests/src/components/contact/VcardModel.hpp b/tests/src/components/contact/VcardModel.hpp index f64ce17e6..709641d12 100644 --- a/tests/src/components/contact/VcardModel.hpp +++ b/tests/src/components/contact/VcardModel.hpp @@ -49,10 +49,10 @@ private: void setUsername (const QString &username); QString getAvatar () const; - void setAvatar (const QString &path); + bool setAvatar (const QString &path); QVariantMap getAddress () const; - void setAddress (const QVariantMap &address); + bool setAddress (const QVariantMap &address); QVariantList getSipAddresses () const; QVariantList getCompanies () const; diff --git a/tests/ui/modules/Common/Image/RoundedImage.qml b/tests/ui/modules/Common/Image/RoundedImage.qml index cc644118d..b32987422 100644 --- a/tests/ui/modules/Common/Image/RoundedImage.qml +++ b/tests/ui/modules/Common/Image/RoundedImage.qml @@ -1,6 +1,6 @@ import QtQuick 2.7 -// =================================================================== +// ============================================================================= Item { id: item @@ -58,6 +58,6 @@ Item { samplerName: 'mask' } - radius: parent.width / 2 + radius: width / 2 } } diff --git a/tests/ui/modules/Linphone/Contact/Avatar.qml b/tests/ui/modules/Linphone/Contact/Avatar.qml index bc38c3a80..d88985c51 100644 --- a/tests/ui/modules/Linphone/Contact/Avatar.qml +++ b/tests/ui/modules/Linphone/Contact/Avatar.qml @@ -5,7 +5,7 @@ import Linphone 1.0 import Linphone.Styles 1.0 import Utils 1.0 -// =================================================================== +// ============================================================================= Item { id: avatar @@ -17,7 +17,7 @@ Item { property var _initialsRegex: /^\s*([^\s\.]+)(?:[\s\.]+([^\s\.]+))?/ - // ----------------------------------------------------------------- + // --------------------------------------------------------------------------- function isLoaded () { return roundedImage.status === Image.Ready @@ -28,7 +28,7 @@ Item { Utils.assert( result != null, - 'Unable to get initials of: \'' + username + '\'' + 'Unable to get initials of: `' + username + '`.' ) return result[1].charAt(0).toUpperCase() + ( @@ -38,7 +38,7 @@ Item { ) } - // ----------------------------------------------------------------- + // --------------------------------------------------------------------------- RoundedImage { id: roundedImage diff --git a/tests/ui/modules/Linphone/Contact/Contact.qml b/tests/ui/modules/Linphone/Contact/Contact.qml index 68f4f53cb..875140b14 100644 --- a/tests/ui/modules/Linphone/Contact/Contact.qml +++ b/tests/ui/modules/Linphone/Contact/Contact.qml @@ -5,9 +5,8 @@ import Common 1.0 import Linphone 1.0 import LinphoneUtils 1.0 import Linphone.Styles 1.0 -import Utils 1.0 -// =================================================================== +// ============================================================================= Rectangle { id: item @@ -15,12 +14,8 @@ Rectangle { property alias actions: actionBar.data property alias sipAddressColor: description.sipAddressColor property alias usernameColor: description.usernameColor - - // Can be a contact object or just a sip address. - property var contact - - // Override contact.sipAddress if used. - property var sipAddress + property string sipAddress + property var _contact: ContactsListModel.mapSipAddressToContact(sipAddress) color: 'transparent' // No color by default. height: ContactStyle.height @@ -38,9 +33,9 @@ Rectangle { Layout.preferredHeight: ContactStyle.contentHeight Layout.preferredWidth: ContactStyle.contentHeight - image: contact.avatar - presenceLevel: contact.presenceLevel || Presence.White - username: LinphoneUtils.getContactUsername(contact) + image: _contact && _contact.vcard.avatar + presenceLevel: _contact ? contact.presenceLevel : Presence.White + username: LinphoneUtils.getContactUsername(_contact || sipAddress) } ContactDescription { @@ -48,9 +43,7 @@ Rectangle { Layout.fillHeight: true Layout.fillWidth: true - sipAddress: Utils.isString(contact) - ? contact - : item.sipAddress || contact.sipAddress + sipAddress: item.sipAddress username: avatar.username } diff --git a/tests/ui/modules/Linphone/Contact/ContactDescription.qml b/tests/ui/modules/Linphone/Contact/ContactDescription.qml index fa69de0cd..b2555fe42 100644 --- a/tests/ui/modules/Linphone/Contact/ContactDescription.qml +++ b/tests/ui/modules/Linphone/Contact/ContactDescription.qml @@ -2,7 +2,7 @@ import QtQuick 2.7 import Linphone.Styles 1.0 -// =================================================================== +// ============================================================================= Column { property alias sipAddress: sipAddress.text @@ -11,7 +11,6 @@ Column { property color usernameColor: ContactDescriptionStyle.username.color property int horizontalTextAlignment - // Username. Text { id: username @@ -25,7 +24,6 @@ Column { width: parent.width } - // Sip address. Text { id: sipAddress diff --git a/tests/ui/modules/Linphone/SmartSearchBar.qml b/tests/ui/modules/Linphone/SmartSearchBar.qml index 436624278..74e16f5be 100644 --- a/tests/ui/modules/Linphone/SmartSearchBar.qml +++ b/tests/ui/modules/Linphone/SmartSearchBar.qml @@ -7,7 +7,7 @@ SearchBox { id: searchBox delegate: Contact { - contact: $contact + // contact: $contact width: parent.width actions: [ diff --git a/tests/ui/modules/Linphone/Timeline.qml b/tests/ui/modules/Linphone/Timeline.qml index 8a98f050e..3b57c576f 100644 --- a/tests/ui/modules/Linphone/Timeline.qml +++ b/tests/ui/modules/Linphone/Timeline.qml @@ -87,7 +87,6 @@ ColumnLayout { ? TimelineStyle.contact.backgroundColor.a : TimelineStyle.contact.backgroundColor.b ) - contact: parent.contact sipAddress: $timelineEntry.sipAddresses sipAddressColor: view.currentIndex === index ? TimelineStyle.contact.sipAddress.color.selected @@ -100,7 +99,8 @@ ColumnLayout { anchors.fill: parent sourceComponent: TooltipArea { text: $timelineEntry.timestamp.toLocaleString( - Qt.locale(App.locale()), Locale.ShortFormat + Qt.locale(App.locale()), + Locale.ShortFormat ) } } diff --git a/tests/ui/scripts/LinphoneUtils/linphone-utils.js b/tests/ui/scripts/LinphoneUtils/linphone-utils.js index 6db035454..8f97e3fca 100644 --- a/tests/ui/scripts/LinphoneUtils/linphone-utils.js +++ b/tests/ui/scripts/LinphoneUtils/linphone-utils.js @@ -10,5 +10,5 @@ function getContactUsername (contact) { return Utils.isString(contact) ? contact.substring(4, contact.indexOf('@')) // 4 = length("sip:") - : contact.username + : contact.vcard.username } diff --git a/tests/ui/scripts/Utils/uri-tools.js b/tests/ui/scripts/Utils/uri-tools.js index 0e5367ed3..eeedfe941 100644 --- a/tests/ui/scripts/Utils/uri-tools.js +++ b/tests/ui/scripts/Utils/uri-tools.js @@ -1,6 +1,6 @@ -// =================================================================== +// ============================================================================= // Library to deal with URI. -// =================================================================== +// ============================================================================= .pragma library @@ -10,7 +10,7 @@ // Not standard but helpful. var SUPPORTS_URL = true -// Level 0. ---------------------------------------------------------- +// Level 0. -------------------------------------------------------------------- var URI_PCT_ENCODED = '%[A-Fa-f\\d]{2}' var URI_PORT = '\\d*' @@ -18,7 +18,7 @@ var URI_SCHEME = '[a-zA-Z][\\w+\-\.]*' var URI_SUB_DELIMS = '[!$&\'()*+,;=]' var URI_UNRESERVED = '[\\w\-\._~]' -// Level 1. ---------------------------------------------------------- +// Level 1. -------------------------------------------------------------------- var URI_HOST = '(' + '(' + @@ -42,7 +42,7 @@ var URI_USERINFO = '(?:' + '|' + ':' + ')*' -// Level 2. ---------------------------------------------------------- +// Level 2. -------------------------------------------------------------------- var URI_AUTHORITY = '(?:' + URI_USERINFO + '@' + ')?' + URI_HOST + @@ -61,7 +61,7 @@ var URI_QUERY = '(?:' + var URI_SEGMENT = URI_PCHAR + '*' var URI_SEGMENT_NZ = URI_PCHAR + '+' -// Level 3. ---------------------------------------------------------- +// Level 3. -------------------------------------------------------------------- var URI_PATH_ABEMPTY = '(?:' + '/' + URI_SEGMENT + ')*' @@ -71,7 +71,7 @@ var URI_PATH_ABSOLUTE = '/' + var URI_PATH_ROOTLESS = URI_SEGMENT_NZ + '(?:' + '/' + URI_SEGMENT + ')*' -// Level 4. ---------------------------------------------------------- +// Level 4. -------------------------------------------------------------------- // `path-empty` not used. var URI_HIER_PART = '(?:' + @@ -80,7 +80,7 @@ var URI_HIER_PART = '(?:' + '|' + URI_PATH_ROOTLESS + ')' -// Level 5. ---------------------------------------------------------- +// Level 5. -------------------------------------------------------------------- // Regex to match URI. It respects the RFC 3986. // But many features are not supported like IP format. @@ -92,7 +92,7 @@ var URI = (SUPPORTS_URL var URI_REGEX = new RegExp(URI, 'g') -// =================================================================== +// ============================================================================= /* TODO: Supports: diff --git a/tests/ui/views/App/Calls/Incall.qml b/tests/ui/views/App/Calls/Incall.qml index ac7a5f1ca..32928ac54 100644 --- a/tests/ui/views/App/Calls/Incall.qml +++ b/tests/ui/views/App/Calls/Incall.qml @@ -110,7 +110,7 @@ Rectangle { } backgroundColor: StartingCallStyle.avatar.backgroundColor - image: _contact.avatar + image: _contact.vcard.avatar username: contactDescription.username height: _computeAvatarSize() diff --git a/tests/ui/views/App/MainWindow/Contacts.qml b/tests/ui/views/App/MainWindow/Contacts.qml index d477e48bd..d307bd51d 100644 --- a/tests/ui/views/App/MainWindow/Contacts.qml +++ b/tests/ui/views/App/MainWindow/Contacts.qml @@ -7,7 +7,7 @@ import Utils 1.0 import App.Styles 1.0 -// =================================================================== +// ============================================================================= ColumnLayout { function _removeContact (contact) { @@ -24,9 +24,9 @@ ColumnLayout { spacing: 0 - // ----------------------------------------------------------------- + // --------------------------------------------------------------------------- // Search Bar & actions. - // ----------------------------------------------------------------- + // --------------------------------------------------------------------------- Rectangle { Layout.fillWidth: true @@ -66,9 +66,9 @@ ColumnLayout { } } - // ----------------------------------------------------------------- + // --------------------------------------------------------------------------- // Contacts list. - // ----------------------------------------------------------------- + // --------------------------------------------------------------------------- Rectangle { Layout.fillWidth: true @@ -89,7 +89,7 @@ ColumnLayout { height: ContactsStyle.contact.height width: parent.width - // ----------------------------------------------------------- + // --------------------------------------------------------------------- Rectangle { id: contact @@ -97,7 +97,7 @@ ColumnLayout { anchors.fill: parent color: ContactsStyle.contact.backgroundColor.normal - // --------------------------------------------------------- + // ------------------------------------------------------------------- Component { id: container1 @@ -142,7 +142,7 @@ ColumnLayout { ActionButton { icon: 'chat' onClicked: window.setView('Conversation', { - sipAddress: $contact.sipAddress + sipAddress: $contact.vcard.sipAddresses[0] // FIXME: Display menu if many addresses. }) } } @@ -160,7 +160,7 @@ ColumnLayout { } } - // --------------------------------------------------------- + // ------------------------------------------------------------------- Rectangle { id: indicator @@ -185,15 +185,13 @@ ColumnLayout { } spacing: ContactsStyle.contact.spacing - // Avatar. Avatar { Layout.preferredHeight: ContactsStyle.contact.avatarSize Layout.preferredWidth: ContactsStyle.contact.avatarSize - image: $contact.avatar - username: $contact.username + image: $contact.vcard.avatar + username: $contact.vcard.username } - // Username. Text { Layout.preferredWidth: ContactsStyle.contact.username.width color: ContactsStyle.contact.username.color @@ -204,7 +202,7 @@ ColumnLayout { pointSize: ContactsStyle.contact.username.fontSize } - text: $contact.username + text: $contact.vcard.username MouseArea { anchors.fill: parent @@ -214,7 +212,7 @@ ColumnLayout { hoverEnabled: true onClicked: window.setView('ContactEdit', { - sipAddress: $contact.sipAddress + sipAddress: $contact.vcard.sipAddresses[0] // FIXME: Display menu if many addresses. }) } } @@ -230,7 +228,7 @@ ColumnLayout { } } - // --------------------------------------------------------- + // ------------------------------------------------------------------- states: State { when: mouseArea.containsMouse diff --git a/tests/ui/views/App/MainWindow/Home.qml b/tests/ui/views/App/MainWindow/Home.qml index 84febd6c4..56563d465 100644 --- a/tests/ui/views/App/MainWindow/Home.qml +++ b/tests/ui/views/App/MainWindow/Home.qml @@ -4,7 +4,7 @@ import QtQuick.Layouts 1.3 import Common 1.0 import Linphone 1.0 -// =================================================================== +// ============================================================================= ColumnLayout { spacing: 0 diff --git a/tests/ui/views/App/MainWindow/MainWindow.qml b/tests/ui/views/App/MainWindow/MainWindow.qml index 1fe771d39..1d5a2eabe 100644 --- a/tests/ui/views/App/MainWindow/MainWindow.qml +++ b/tests/ui/views/App/MainWindow/MainWindow.qml @@ -8,7 +8,7 @@ import Utils 1.0 import App.Styles 1.0 -// =================================================================== +// ============================================================================= ApplicationWindow { id: window @@ -17,9 +17,9 @@ ApplicationWindow { contentLoader.setSource(view + '.qml', props || {}) } - // ----------------------------------------------------------------- + // --------------------------------------------------------------------------- // Window properties. - // ----------------------------------------------------------------- + // --------------------------------------------------------------------------- maximumHeight: MainWindowStyle.toolBar.height minimumHeight: MainWindowStyle.toolBar.height @@ -30,9 +30,9 @@ ApplicationWindow { onActiveFocusItemChanged: activeFocusItem == null && smartSearchBar.hideMenu() - // ----------------------------------------------------------------- + // --------------------------------------------------------------------------- // Toolbar properties. - // ----------------------------------------------------------------- + // --------------------------------------------------------------------------- header: ToolBar { background: MainWindowStyle.toolBar.background @@ -94,9 +94,9 @@ ApplicationWindow { } } - // ----------------------------------------------------------------- + // --------------------------------------------------------------------------- // Content. - // ----------------------------------------------------------------- + // --------------------------------------------------------------------------- RowLayout { anchors.fill: parent