diff --git a/Linphone/core/account/AccountCore.cpp b/Linphone/core/account/AccountCore.cpp index 5f5c76b39..7a39e5746 100644 --- a/Linphone/core/account/AccountCore.cpp +++ b/Linphone/core/account/AccountCore.cpp @@ -20,7 +20,6 @@ #include "AccountCore.hpp" #include "core/App.hpp" -#include "model/core/CoreModel.hpp" #include "tool/Utils.hpp" #include "tool/thread/SafeConnection.hpp" @@ -95,6 +94,20 @@ void AccountCore::setSelf(QSharedPointer me) { mAccountModelConnection->makeConnectToCore(&AccountCore::lResetMissedCalls, [this]() { mAccountModelConnection->invokeToModel([this]() { mAccountModel->resetMissedCallsCount(); }); }); + mAccountModelConnection->makeConnectToCore(&AccountCore::lRefreshNotifications, [this]() { + mAccountModelConnection->invokeToModel([this]() { mAccountModel->refreshUnreadNotifications(); }); + }); + mCoreModelConnection = QSharedPointer>( + new SafeConnection(me, CoreModel::getInstance())); + mAccountModelConnection->makeConnectToCore(&AccountCore::unreadCallNotificationsChanged, [this]() { + mAccountModelConnection->invokeToModel([this]() { CoreModel::getInstance()->unreadNotificationsChanged(); }); + }); + mAccountModelConnection->makeConnectToCore(&AccountCore::unreadMessageNotificationsChanged, [this]() { + mAccountModelConnection->invokeToModel([this]() { CoreModel::getInstance()->unreadNotificationsChanged(); }); + }); + mAccountModelConnection->makeConnectToCore(&AccountCore::unreadNotificationsChanged, [this]() { + mAccountModelConnection->invokeToModel([this]() { CoreModel::getInstance()->unreadNotificationsChanged(); }); + }); } QString AccountCore::getContactAddress() const { @@ -133,7 +146,7 @@ int AccountCore::getUnreadCallNotifications() const { void AccountCore::setUnreadCallNotifications(int unread) { if (mUnreadCallNotifications != unread) { mUnreadCallNotifications = unread; - emit unreadNotificationsChanged(unread); + emit unreadCallNotificationsChanged(unread); } } @@ -143,7 +156,7 @@ int AccountCore::getUnreadMessageNotifications() const { void AccountCore::setUnreadMessageNotifications(int unread) { if (mUnreadMessageNotifications != unread) { mUnreadMessageNotifications = unread; - emit unreadNotificationsChanged(unread); + emit unreadMessageNotificationsChanged(unread); } } diff --git a/Linphone/core/account/AccountCore.hpp b/Linphone/core/account/AccountCore.hpp index e4876a822..4d33c8e71 100644 --- a/Linphone/core/account/AccountCore.hpp +++ b/Linphone/core/account/AccountCore.hpp @@ -38,8 +38,9 @@ class AccountCore : public QObject, public AbstractObject { LinphoneEnums::RegistrationState registrationState READ getRegistrationState NOTIFY registrationStateChanged) Q_PROPERTY(bool isDefaultAccount READ getIsDefaultAccount NOTIFY defaultAccountChanged) Q_PROPERTY(int unreadNotifications READ getUnreadNotifications NOTIFY unreadNotificationsChanged) - Q_PROPERTY(int unreadCallNotifications READ getUnreadCallNotifications NOTIFY unreadNotificationsChanged) - Q_PROPERTY(int unreadMessageNotifications READ getUnreadMessageNotifications NOTIFY unreadNotificationsChanged) + Q_PROPERTY(int unreadCallNotifications READ getUnreadCallNotifications NOTIFY unreadCallNotificationsChanged) + Q_PROPERTY( + int unreadMessageNotifications READ getUnreadMessageNotifications NOTIFY unreadMessageNotificationsChanged) public: static QSharedPointer create(const std::shared_ptr &account); @@ -72,12 +73,15 @@ signals: void pictureUriChanged(); void registrationStateChanged(const QString &message); void defaultAccountChanged(bool isDefault); - void unreadNotificationsChanged(int unreadNotifications); + void unreadNotificationsChanged(int unread); + void unreadCallNotificationsChanged(int unread); + void unreadMessageNotificationsChanged(int unread); // Account requests void lSetPictureUri(QString pictureUri); void lSetDefaultAccount(); void lResetMissedCalls(); + void lRefreshNotifications(); private: QString mContactAddress; @@ -90,6 +94,7 @@ private: int mUnreadMessageNotifications = 0; std::shared_ptr mAccountModel; QSharedPointer> mAccountModelConnection; + QSharedPointer> mCoreModelConnection; DECLARE_ABSTRACT_OBJECT }; diff --git a/Linphone/core/conference/ConferenceCore.hpp b/Linphone/core/conference/ConferenceCore.hpp index 34dca0e29..be234b86c 100644 --- a/Linphone/core/conference/ConferenceCore.hpp +++ b/Linphone/core/conference/ConferenceCore.hpp @@ -36,7 +36,6 @@ class ConferenceCore : public QObject, public AbstractObject { Q_OBJECT public: - Q_PROPERTY(QString subject READ getSubject NOTIFY subjectChanged) Q_PROPERTY(QDateTime startDate READ getStartDate CONSTANT) // Q_PROPERTY(ParticipantDeviceList *participantDevices READ getParticipantDeviceList CONSTANT) // Q_PROPERTY(ParticipantModel* localParticipant READ getLocalParticipant NOTIFY localParticipantChanged) @@ -72,7 +71,6 @@ public: //--------------------------------------------------------------------------- signals: - void subjectChanged(); void isReadyChanged(); void participantDeviceCountChanged(); void activeSpeakerChanged(); diff --git a/Linphone/core/conference/ConferenceInfoList.cpp b/Linphone/core/conference/ConferenceInfoList.cpp index 155c7a584..ac0c92abf 100644 --- a/Linphone/core/conference/ConferenceInfoList.cpp +++ b/Linphone/core/conference/ConferenceInfoList.cpp @@ -55,8 +55,10 @@ void ConferenceInfoList::setSelf(QSharedPointer me) { mCoreModelConnection->invokeToModel([this]() { QList> *items = new QList>(); mustBeInLinphoneThread(getClassName()); + auto defaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount(); + if (!defaultAccount) return; std::list> conferenceInfos = - CoreModel::getInstance()->getCore()->getDefaultAccount()->getConferenceInformationList(); + defaultAccount->getConferenceInformationList(); items->push_back(nullptr); // Add Dummy conference for today for (auto conferenceInfo : conferenceInfos) { auto confInfoCore = build(conferenceInfo); diff --git a/Linphone/core/friend/FriendCore.cpp b/Linphone/core/friend/FriendCore.cpp index 198b43add..92a0f5218 100644 --- a/Linphone/core/friend/FriendCore.cpp +++ b/Linphone/core/friend/FriendCore.cpp @@ -59,6 +59,7 @@ FriendCore::FriendCore(const std::shared_ptr &contact) : QObje mJob = Utils::coreStringToAppString(vcard->getJobTitle()); mGivenName = Utils::coreStringToAppString(vcard->getGivenName()); mFamilyName = Utils::coreStringToAppString(vcard->getFamilyName()); + mVCardString = Utils::coreStringToAppString(vcard->asVcard4String()); } auto addresses = contact->getAddresses(); for (auto &address : addresses) { @@ -80,6 +81,7 @@ FriendCore::FriendCore(const std::shared_ptr &contact) : QObje mIsSaved = false; mStarred = false; } + connect(this, &FriendCore::addressChanged, &FriendCore::allAddressesChanged); connect(this, &FriendCore::phoneNumberChanged, &FriendCore::allAddressesChanged); } @@ -247,6 +249,10 @@ void FriendCore::onStarredChanged(bool starred) { emit starredChanged(); } +QString FriendCore::getVCard() const { + return mVCardString; +} + QList FriendCore::getPhoneNumbers() const { return mPhoneNumberList; } @@ -480,6 +486,7 @@ void FriendCore::save() { // Save Values to model mustBeInLinphoneThread(getClassName() + "::save()"); thisCopy->writeIntoModel(mFriendModel); thisCopy->deleteLater(); + mVCardString = mFriendModel->getVCardAsString(); mFriendModelConnection->invokeToCore([this]() { saved(); }); setIsSaved(true); }); @@ -501,6 +508,7 @@ void FriendCore::save() { // Save Values to model mCoreModelConnection->invokeToModel([this, thisCopy] { thisCopy->writeIntoModel(mFriendModel); thisCopy->deleteLater(); + mVCardString = mFriendModel->getVCardAsString(); }); saved(); }); @@ -514,6 +522,7 @@ void FriendCore::save() { // Save Values to model auto core = CoreModel::getInstance()->getCore(); thisCopy->writeIntoModel(mFriendModel); thisCopy->deleteLater(); + mVCardString = mFriendModel->getVCardAsString(); bool created = (core->getDefaultFriendList()->addFriend(contact) == linphone::FriendList::Status::OK); if (created) { diff --git a/Linphone/core/friend/FriendCore.hpp b/Linphone/core/friend/FriendCore.hpp index 6c60d9b5f..730501b78 100644 --- a/Linphone/core/friend/FriendCore.hpp +++ b/Linphone/core/friend/FriendCore.hpp @@ -87,6 +87,8 @@ public: bool getStarred() const; void onStarredChanged(bool starred); + Q_INVOKABLE QString getVCard() const; + QList getPhoneNumbers() const; QVariant getPhoneNumberAt(int index) const; Q_INVOKABLE void appendPhoneNumber(const QString &label, const QString &number); @@ -164,6 +166,7 @@ protected: QString mDefaultAddress; QString mPictureUri; bool mIsSaved; + QString mVCardString; std::shared_ptr mFriendModel; QSharedPointer> mFriendModelConnection; QSharedPointer> mCoreModelConnection; diff --git a/Linphone/core/notifier/Notifier.cpp b/Linphone/core/notifier/Notifier.cpp index 3627f370c..1396e7be1 100644 --- a/Linphone/core/notifier/Notifier.cpp +++ b/Linphone/core/notifier/Notifier.cpp @@ -176,7 +176,7 @@ QObject *Notifier::createNotification(Notifier::NotificationType type, QVariantM engine->deleteLater(); exit(-1); } else { - qWarning() << engine->rootObjects()[0]; + lDebug() << engine->rootObjects()[0]; auto window = qobject_cast(obj); if (window) { int *screenHeightOffset = &mScreenHeightOffset[screen->name()]; // Access optimization @@ -191,7 +191,7 @@ QObject *Notifier::createNotification(Notifier::NotificationType type, QVariantM window->property("width") .toInt())); //*screen->devicePixelRatio()); when using manual scaler window->setY(heightOffset - (*screenHeightOffset % heightOffset)); - qWarning() << window->geometry(); + lDebug() << window->geometry(); } } }, diff --git a/Linphone/model/account/AccountManager.cpp b/Linphone/model/account/AccountManager.cpp index c7625bb9f..3e7aed757 100644 --- a/Linphone/model/account/AccountManager.cpp +++ b/Linphone/model/account/AccountManager.cpp @@ -66,6 +66,7 @@ bool AccountManager::login(QString username, QString password, QString *errorMes } } + username = Utils::getUsername(username); identity->setUsername(Utils::appStringToCoreString(username)); if (params->setIdentityAddress(identity)) { qWarning() << log() diff --git a/Linphone/model/account/AccountModel.cpp b/Linphone/model/account/AccountModel.cpp index a76ec6879..f0207e8aa 100644 --- a/Linphone/model/account/AccountModel.cpp +++ b/Linphone/model/account/AccountModel.cpp @@ -94,4 +94,17 @@ void AccountModel::resetMissedCallsCount() { mMonitor->resetMissedCallsCount(); emit unreadNotificationsChanged(0 /*mMonitor->getUnreadChatMessageCount()*/, mMonitor->getMissedCallsCount()); // TODO +} + +void AccountModel::refreshUnreadNotifications() { + emit unreadNotificationsChanged(0 /*mMonitor->getUnreadChatMessageCount()*/, + mMonitor->getMissedCallsCount()); // TODO +} + +int AccountModel::getMissedCallsCount() const { + return mMonitor->getMissedCallsCount(); +} + +int AccountModel::getUnreadMessagesCount() const { + return mMonitor->getUnreadChatMessageCount(); } \ No newline at end of file diff --git a/Linphone/model/account/AccountModel.hpp b/Linphone/model/account/AccountModel.hpp index 0b21260c6..cc181e066 100644 --- a/Linphone/model/account/AccountModel.hpp +++ b/Linphone/model/account/AccountModel.hpp @@ -44,6 +44,9 @@ public: void setDefault(); void removeAccount(); void resetMissedCallsCount(); + void refreshUnreadNotifications(); + int getMissedCallsCount() const; + int getUnreadMessagesCount() const; signals: void registrationStateChanged(const std::shared_ptr &account, diff --git a/Linphone/model/friend/FriendModel.cpp b/Linphone/model/friend/FriendModel.cpp index da917db51..31b59be19 100644 --- a/Linphone/model/friend/FriendModel.cpp +++ b/Linphone/model/friend/FriendModel.cpp @@ -141,11 +141,22 @@ void FriendModel::clearAddresses() { } QString FriendModel::getName() const { - return Utils::coreStringToAppString(mMonitor->getName()); + auto vcard = mMonitor->getVcard(); + bool created = false; + if (!vcard) { + created = mMonitor->createVcard(mMonitor->getName()); + } + if (mMonitor->getVcard()) return Utils::coreStringToAppString(mMonitor->getName()); + else return QString(); } void FriendModel::setName(const QString &name) { - mMonitor->setName(Utils::appStringToCoreString(name)); + auto vcard = mMonitor->getVcard(); + bool created = false; + if (!vcard) { + created = mMonitor->createVcard(Utils::appStringToCoreString(name)); + } + if (mMonitor->getVcard()) mMonitor->setName(Utils::appStringToCoreString(name)); } QString FriendModel::getGivenName() const { @@ -259,6 +270,11 @@ QString FriendModel::getPictureUri() const { else return QString(); } +QString FriendModel::getVCardAsString() const { + assert(mMonitor->getVcard()); + return Utils::coreStringToAppString(mMonitor->getVcard()->asVcard4String()); +} + void FriendModel::setPictureUri(const QString &uri) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); auto oldPictureUri = Utils::coreStringToAppString(mMonitor->getPhoto()); diff --git a/Linphone/model/friend/FriendModel.hpp b/Linphone/model/friend/FriendModel.hpp index 8b85ba088..5e5ffe5cb 100644 --- a/Linphone/model/friend/FriendModel.hpp +++ b/Linphone/model/friend/FriendModel.hpp @@ -53,6 +53,7 @@ public: bool getStarred() const; std::shared_ptr getFriend() const; QString getPictureUri() const; + QString getVCardAsString() const; protected: void setAddress(const std::shared_ptr &address); diff --git a/Linphone/tool/Utils.cpp b/Linphone/tool/Utils.cpp index 4c194763a..155e92425 100644 --- a/Linphone/tool/Utils.cpp +++ b/Linphone/tool/Utils.cpp @@ -62,6 +62,14 @@ VariantObject *Utils::getDisplayName(const QString &address) { return data; } +QString Utils::getUsername(const QString &address) { + QString res = address; + if (res.startsWith("sip:")) res.remove("sip:"); + int splitIndex = res.lastIndexOf('@'); + if (splitIndex != -1) res.truncate(splitIndex); + return res; +} + QString Utils::getGivenNameFromFullName(const QString &fullName) { if (fullName.isEmpty()) return QString(); auto nameSplitted = fullName.split(" "); diff --git a/Linphone/tool/Utils.hpp b/Linphone/tool/Utils.hpp index 8455d4510..e5dfa17c0 100644 --- a/Linphone/tool/Utils.hpp +++ b/Linphone/tool/Utils.hpp @@ -54,6 +54,7 @@ public: } Q_INVOKABLE static VariantObject *getDisplayName(const QString &address); + Q_INVOKABLE static QString getUsername(const QString &address); Q_INVOKABLE static QString getGivenNameFromFullName(const QString &fullName); Q_INVOKABLE static QString getFamilyNameFromFullName(const QString &fullName); Q_INVOKABLE static QString getInitials(const QString &username); // Support UTF32 diff --git a/Linphone/view/App/Layout/MainLayout.qml b/Linphone/view/App/Layout/MainLayout.qml index c7d0dc33b..0c685087e 100644 --- a/Linphone/view/App/Layout/MainLayout.qml +++ b/Linphone/view/App/Layout/MainLayout.qml @@ -31,6 +31,11 @@ Item { contactPage.createContact(name, address) } + AccountProxy { + id: accountProxy + onDefaultAccountChanged: if (tabbar.currentIndex === 0) defaultAccount.core.lResetMissedCalls() + } + Timer { id: autoClosePopup interval: 5000 @@ -120,11 +125,13 @@ Item { id: tabbar Layout.fillHeight: true Layout.preferredWidth: 82 * DefaultStyle.dp + defaultAccount: accountProxy.defaultAccount + property int unreadMessages: defaultAccount.core.unreadMessageNotifications model: [ - {icon: AppIcons.phone, selectedIcon: AppIcons.phoneSelected, label: qsTr("Appels"), unreadNotifications: accountProxy.defaultAccount.core.unreadCallNotifications}, - {icon: AppIcons.adressBook, selectedIcon: AppIcons.adressBookSelected, label: qsTr("Contacts"), unreadNotifications: 0}, - {icon: AppIcons.chatTeardropText, selectedIcon: AppIcons.chatTeardropTextSelected, label: qsTr("Conversations"), unreadNotifications: accountProxy.defaultAccount.core.unreadMessageNotifications}, - {icon: AppIcons.videoconference, selectedIcon: AppIcons.videoconferenceSelected, label: qsTr("Réunions"), unreadNotifications: 0} + {icon: AppIcons.phone, selectedIcon: AppIcons.phoneSelected, label: qsTr("Appels")}, + {icon: AppIcons.adressBook, selectedIcon: AppIcons.adressBookSelected, label: qsTr("Contacts")}, + {icon: AppIcons.chatTeardropText, selectedIcon: AppIcons.chatTeardropTextSelected, label: qsTr("Conversations")}, + {icon: AppIcons.videoconference, selectedIcon: AppIcons.videoconferenceSelected, label: qsTr("Réunions")} ] onCurrentIndexChanged: { if (currentIndex === 0) accountProxy.defaultAccount.core.lResetMissedCalls() @@ -294,10 +301,6 @@ Item { spacing: 10 * DefaultStyle.dp PopupButton { id: avatarButton - AccountProxy{ - id: accountProxy - //property bool haveAvatar: defaultAccount && defaultAccount.core.pictureUri || false - } background.visible: false Layout.preferredWidth: 54 * DefaultStyle.dp Layout.preferredHeight: width @@ -312,6 +315,7 @@ Item { popup.contentItem: ColumnLayout { Accounts { id: accounts + accountProxy: accountProxy onAddAccountRequest: mainItem.addAccountRequest() } } diff --git a/Linphone/view/Item/Account/Accounts.qml b/Linphone/view/Item/Account/Accounts.qml index c66a11b29..ecfda7852 100644 --- a/Linphone/view/Item/Account/Accounts.qml +++ b/Linphone/view/Item/Account/Accounts.qml @@ -15,6 +15,7 @@ Item { readonly property int leftPadding: 32 * DefaultStyle.dp readonly property int rightPadding: 32 * DefaultStyle.dp readonly property int spacing: 16 * DefaultStyle.dp + property AccountProxy accountProxy signal addAccountRequest() implicitHeight: list.contentHeight + topPadding + bottomPadding + 32 * DefaultStyle.dp + 1 + newAccountArea.height @@ -33,7 +34,7 @@ Item { Layout.preferredHeight: contentHeight Layout.fillWidth: true spacing: mainItem.spacing - model: AccountProxy{} + model: mainItem.accountProxy delegate: Contact{ id: contactItem width: list.width diff --git a/Linphone/view/Item/Call/CallContactsLists.qml b/Linphone/view/Item/Call/CallContactsLists.qml index 4c2bd5521..c6f1cff59 100644 --- a/Linphone/view/Item/Call/CallContactsLists.qml +++ b/Linphone/view/Item/Call/CallContactsLists.qml @@ -210,14 +210,14 @@ Item { model: MagicSearchProxy { searchText: searchBar.text.length === 0 ? "*" : searchBar.text } - onSelectedContactChanged: { - if (selectedContact) { - if (selectedContact.core.allAddresses.length > 1) { - startCallPopup.contact = selectedContact + onContactClicked: (contact) => { + if (contact) { + if (contact.core.allAddresses.length > 1) { + startCallPopup.contact = contact startCallPopup.open() } else { - mainItem.callButtonPressed(selectedContact.core.defaultAddress) + mainItem.callButtonPressed(contact.core.defaultAddress) } } } diff --git a/Linphone/view/Item/Call/WaitingRoom.qml b/Linphone/view/Item/Call/WaitingRoom.qml index 8a1048a58..fe26edc29 100644 --- a/Linphone/view/Item/Call/WaitingRoom.qml +++ b/Linphone/view/Item/Call/WaitingRoom.qml @@ -42,13 +42,14 @@ RowLayout { id: videoButton iconUrl: AppIcons.videoCamera checkedIconUrl: AppIcons.videoCameraSlash + checked: !mainItem.localVideoEnabled color: DefaultStyle.grey_500 contentImageColor: DefaultStyle.main2_0 Layout.preferredWidth: 55 * DefaultStyle.dp Layout.preferredHeight: 55 * DefaultStyle.dp icon.width: 32 * DefaultStyle.dp icon.height: 32 * DefaultStyle.dp - onCheckedChanged: mainItem.localVideoEnabled = !mainItem.localVideoEnabled + onClicked: mainItem.localVideoEnabled = !mainItem.localVideoEnabled } CheckableButton { id: microButton diff --git a/Linphone/view/Item/Contact/Contact.qml b/Linphone/view/Item/Contact/Contact.qml index d1772d05e..ed7ec45f9 100644 --- a/Linphone/view/Item/Contact/Contact.qml +++ b/Linphone/view/Item/Contact/Contact.qml @@ -11,6 +11,7 @@ import UtilsCpp Rectangle{ id: mainItem property AccountGui account + signal avatarClicked() signal backgroundClicked() @@ -22,25 +23,27 @@ Rectangle{ RowLayout{ anchors.fill: parent spacing: 0 - Avatar{ - id: avatar - Layout.preferredWidth: 45 * DefaultStyle.dp - Layout.preferredHeight: 45 * DefaultStyle.dp - account: mainItem.account - MouseArea{ - anchors.fill: parent - onClicked: mainItem.avatarClicked() - } - } - Item { - Layout.preferredWidth: 200 * DefaultStyle.dp - Layout.fillHeight: true - Layout.leftMargin: 10 * DefaultStyle.dp - Layout.rightMargin: 10 * DefaultStyle.dp - ContactDescription{ - id: description - anchors.fill: parent + RowLayout { + spacing: 10 * DefaultStyle.dp + Avatar{ + id: avatar + Layout.preferredWidth: 45 * DefaultStyle.dp + Layout.preferredHeight: 45 * DefaultStyle.dp account: mainItem.account + MouseArea{ + anchors.fill: parent + onClicked: mainItem.avatarClicked() + } + } + Item { + Layout.preferredWidth: 200 * DefaultStyle.dp + Layout.fillHeight: true + Layout.rightMargin: 10 * DefaultStyle.dp + ContactDescription{ + id: description + anchors.fill: parent + account: mainItem.account + } } } Control.Control { @@ -96,20 +99,17 @@ Rectangle{ : qsTr("Erreur") } } - // Item { - // Layout.fillWidth: true - // } Item{ - Layout.preferredWidth: 27 * DefaultStyle.dp - Layout.preferredHeight: 27 * DefaultStyle.dp + Layout.preferredWidth: 26 * DefaultStyle.dp + Layout.preferredHeight: 26 * DefaultStyle.dp Layout.fillHeight: true + Layout.leftMargin: 40 * DefaultStyle.dp + visible: mainItem.account.core.unreadCallNotifications > 0 Rectangle{ id: unreadNotifications anchors.verticalCenter: parent.verticalCenter - property int unread: mainItem.account.core.unreadNotifications - visible: unread > 0 - width: 27 * DefaultStyle.dp - height: 27 * DefaultStyle.dp + width: 26 * DefaultStyle.dp + height: 26 * DefaultStyle.dp radius: width/2 color: DefaultStyle.danger_500main border.color: DefaultStyle.grey_0 @@ -125,7 +125,7 @@ Rectangle{ fontSizeMode: Text.Fit font.pixelSize: 11 * DefaultStyle.dp font.weight: 700 * DefaultStyle.dp - text: parent.unread > 100 ? '99+' : parent.unread + text: mainItem.account.core.unreadCallNotifications >= 100 ? '99+' : mainItem.account.core.unreadCallNotifications } } MultiEffect { @@ -136,6 +136,7 @@ Rectangle{ shadowOpacity: 0.15 } } + Item{Layout.fillWidth: true} EffectImage { id: manageAccount imageSource: AppIcons.manageProfile diff --git a/Linphone/view/Item/Contact/ContactsList.qml b/Linphone/view/Item/Contact/ContactsList.qml index aff76654d..d08411824 100644 --- a/Linphone/view/Item/Contact/ContactsList.qml +++ b/Linphone/view/Item/Contact/ContactsList.qml @@ -45,6 +45,7 @@ ListView { signal contactStarredChanged() signal contactDeletionRequested(FriendGui contact) signal contactAddedToSelection() + signal contactClicked(FriendGui contact) function addContactToSelection(address) { if (multiSelectionEnabled) { @@ -112,7 +113,7 @@ ListView { id: contactDelegate anchors.left: initial.visible ? initial.right : parent.left anchors.leftMargin: 10 * DefaultStyle.dp - anchors.right: parent.right + anchors.right: actionsRow.left // anchors.rightMargin: 10 * DefaultStyle.dp anchors.verticalCenter: parent.verticalCenter spacing: 10 * DefaultStyle.dp @@ -182,7 +183,7 @@ ListView { PopupButton { id: friendPopup z: 1 - Layout.rightMargin: 5 * DefaultStyle.dp + Layout.rightMargin: 13 * DefaultStyle.dp Layout.alignment: Qt.AlignVCenter popup.x: 0 popup.padding: 10 * DefaultStyle.dp @@ -249,8 +250,9 @@ ListView { MouseArea { id: contactArea hoverEnabled: mainItem.hoverEnabled - anchors.fill: contactDelegate + anchors.fill: itemDelegate height: mainItem.height + z: -1 Rectangle { anchors.fill: contactArea opacity: 0.7 @@ -259,6 +261,7 @@ ListView { } onClicked: { mainItem.currentIndex = index + mainItem.contactClicked(modelData) if (mainItem.multiSelectionEnabled) { var indexInSelection = mainItem.selectedContacts.indexOf(modelData.core.defaultAddress) if (indexInSelection == -1) { diff --git a/Linphone/view/Item/Contact/Sticker.qml b/Linphone/view/Item/Contact/Sticker.qml index 6c4caae76..ae8c6ebeb 100644 --- a/Linphone/view/Item/Contact/Sticker.qml +++ b/Linphone/view/Item/Contact/Sticker.qml @@ -82,6 +82,7 @@ Item { Text { id: waitingTime property int seconds + visible: !UtilsCpp.isMe(mainItem.peerAddress) text: UtilsCpp.formatElapsedTime(seconds) color: DefaultStyle.grey_0 Layout.alignment: Qt.AlignHCenter diff --git a/Linphone/view/Item/DesktopPopup.qml b/Linphone/view/Item/DesktopPopup.qml index 3a7396537..e56066a27 100644 --- a/Linphone/view/Item/DesktopPopup.qml +++ b/Linphone/view/Item/DesktopPopup.qml @@ -8,52 +8,53 @@ import Qt.labs.platform 1.0 // ============================================================================= Window { - id: mainItem + id: mainItem - // --------------------------------------------------------------------------- + // --------------------------------------------------------------------------- - - property bool requestActivate: false - //property int flags: Qt.SplashScreen + color: "transparent" + + property bool requestActivate: false + //property int flags: Qt.SplashScreen - + - default property alias _content: content.data - property bool _isOpen: false - signal isOpened() - signal isClosed() - signal dataChanged() + default property alias _content: content.data + property bool _isOpen: false + signal isOpened() + signal isClosed() + signal dataChanged() - on_ContentChanged: dataChanged(_content) - // --------------------------------------------------------------------------- + on_ContentChanged: dataChanged(_content) + // --------------------------------------------------------------------------- - function open () { - _isOpen = true; - isOpened(); - } -/* - function close () { - _isOpen = false - isClosed() - } -*/ - // --------------------------------------------------------------------------- + function open () { + _isOpen = true; + isOpened(); + } + /* + function close () { + _isOpen = false + isClosed() + } + */ + // --------------------------------------------------------------------------- - objectName: '__internalWindow' - property bool isFrameLess : false; - property bool showAsTool : false - // Don't use Popup for flags : it could lead to error in geometry. On Mac, Using Tool ensure to have the Window on Top and fullscreen independant - flags: Qt.BypassWindowManagerHint | (showAsTool?Qt.Tool:Qt.WindowStaysOnTopHint) | Qt.Window | Qt.FramelessWindowHint; - opacity: 1.0 - height: _content[0] != null ? _content[0].height : 0 - width: _content[0] != null ? _content[0].width : 0 - visible:true - Item { - id: content - anchors.fill:parent + objectName: '__internalWindow' + property bool isFrameLess : false; + property bool showAsTool : false + // Don't use Popup for flags : it could lead to error in geometry. On Mac, Using Tool ensure to have the Window on Top and fullscreen independant + flags: Qt.BypassWindowManagerHint | (showAsTool?Qt.Tool:Qt.WindowStaysOnTopHint) | Qt.Window | Qt.FramelessWindowHint; + opacity: 1.0 + height: _content[0] != null ? _content[0].height : 0 + width: _content[0] != null ? _content[0].width : 0 + visible:true + Item { + id: content + anchors.fill:parent - property var $parent: mainItem - } + property var $parent: mainItem + } // --------------------------------------------------------------------------- /* diff --git a/Linphone/view/Item/Form/LoginForm.qml b/Linphone/view/Item/Form/LoginForm.qml index df2e49186..20e701907 100644 --- a/Linphone/view/Item/Form/LoginForm.qml +++ b/Linphone/view/Item/Form/LoginForm.qml @@ -101,10 +101,12 @@ ColumnLayout { target: LoginPageCpp onRegistrationStateChanged: { if (LoginPageCpp.registrationState != LinphoneEnums.RegistrationState.Progress) { + connectionButton.enabled = true connectionButtonContent.currentIndex = 0 } } onErrorMessageChanged: { + connectionButton.enabled = true connectionButtonContent.currentIndex = 0 } } @@ -123,6 +125,7 @@ ColumnLayout { return } LoginPageCpp.login(usernameEdit.text, passwordEdit.text) + connectionButton.enabled = false connectionButtonContent.currentIndex = 1 } diff --git a/Linphone/view/Item/Meeting/MeetingList.qml b/Linphone/view/Item/Meeting/MeetingList.qml index 049ee3199..c42e4e070 100644 --- a/Linphone/view/Item/Meeting/MeetingList.qml +++ b/Linphone/view/Item/Meeting/MeetingList.qml @@ -19,7 +19,7 @@ ListView { spacing: 8 * DefaultStyle.dp currentIndex: confInfoProxy.currentDateIndex - onCountChanged: selectedConference = model && currentIndex != -1 ? model.getAt(currentIndex) : null + onCountChanged: selectedConference = model && currentIndex != -1 && currentIndex < model.count ? model.getAt(currentIndex) : null onCurrentIndexChanged: { selectedConference = model.getAt(currentIndex) } diff --git a/Linphone/view/Item/Notification/Notification.qml b/Linphone/view/Item/Notification/Notification.qml index 671314963..8d59ffa9b 100644 --- a/Linphone/view/Item/Notification/Notification.qml +++ b/Linphone/view/Item/Notification/Notification.qml @@ -1,17 +1,19 @@ import QtQuick 2.7 +import QtQuick.Effects import Linphone // ============================================================================= DesktopPopup { - id: notification + id: mainItem property var notificationData: ({ timelineModel : null }) - property int overriddenHeight - property int overriddenWidth + property int overriddenHeight: 120 * DefaultStyle.dp + property int overriddenWidth: 300 * DefaultStyle.dp + property double radius: 0 default property alias _content: content.data signal deleteNotification (var notification) @@ -29,13 +31,15 @@ DesktopPopup { } Rectangle { - color: "#FFFFFF" - height: overriddenHeight || 120 - width: overriddenWidth || 300 + id: background + color: DefaultStyle.grey_0 + height: mainItem.overriddenHeight + width: mainItem.overriddenWidth + radius: mainItem.radius border { - color: "#A1A1A1" - width: 1 + color: DefaultStyle.grey_400 + width: 1 * DefaultStyle.dp } Item { @@ -55,4 +59,12 @@ DesktopPopup { } } + MultiEffect { + source: background + anchors.fill: background + shadowEnabled: true + shadowColor: DefaultStyle.grey_1000 + shadowOpacity: 0.1 + shadowBlur: 1 + } } diff --git a/Linphone/view/Item/Notification/NotificationReceivedCall.qml b/Linphone/view/Item/Notification/NotificationReceivedCall.qml index 5b92d18d0..4a4bd6d7b 100644 --- a/Linphone/view/Item/Notification/NotificationReceivedCall.qml +++ b/Linphone/view/Item/Notification/NotificationReceivedCall.qml @@ -6,112 +6,95 @@ import UtilsCpp Notification { id: mainItem - - // --------------------------------------------------------------------------- - + radius: 20 * DefaultStyle.dp + overriddenHeight: 101 * DefaultStyle.dp + overriddenWidth: 422 * DefaultStyle.dp + readonly property var call: notificationData && notificationData.call property var state: call.core.state onStateChanged:{ - console.log("state notif", state, this) - if(state != LinphoneEnums.CallState.IncomingReceived){ + if (state != LinphoneEnums.CallState.IncomingReceived){ close() } } - // overridenWidth: 320 * DefaultStyle.dp - // overridenHeight: 150 * DefaultStyle.dp - // --------------------------------------------------------------------------- - ColumnLayout { + + RowLayout { anchors.fill: parent - anchors.leftMargin: 15 - anchors.rightMargin: 15 - anchors.bottomMargin:15 - anchors.topMargin:15 - - // --------------------------------------------------------------------- - // Action buttons. - // --------------------------------------------------------------------- - + anchors.leftMargin: 19 * DefaultStyle.dp + anchors.rightMargin: 19 * DefaultStyle.dp + anchors.bottomMargin: 15 * DefaultStyle.dp + anchors.topMargin: 15 * DefaultStyle.dp + spacing: 30 * DefaultStyle.dp RowLayout { Layout.fillWidth: true Layout.alignment: Qt.AlignLeft - spacing: 15 * DefaultStyle.dp + spacing: 13 * DefaultStyle.dp Avatar { - Layout.preferredWidth: 40 * DefaultStyle.dp - Layout.preferredHeight: 40 * DefaultStyle.dp + Layout.preferredWidth: 45 * DefaultStyle.dp + Layout.preferredHeight: 45 * DefaultStyle.dp call: mainItem.call } ColumnLayout { Text { property var remoteAddress: UtilsCpp.getDisplayName(call.core.peerAddress) text: remoteAddress ? remoteAddress.value : "" + color: DefaultStyle.grey_600 font { - pixelSize: 14 * DefaultStyle.dp - weight: 700 * DefaultStyle.dp + pixelSize: 20 * DefaultStyle.dp + weight: 800 * DefaultStyle.dp + capitalization: Font.Capitalize } } - Text { - text: call.core.peerAddress + RowLayout { + EffectImage { + imageSource: AppIcons.arrowDownLeft + colorizationColor: DefaultStyle.success_500main + Layout.preferredWidth: 24 * DefaultStyle.dp + Layout.preferredHeight: 24 * DefaultStyle.dp + } + Text { + Layout.fillWidth: true + elide: Text.ElideRight + property var localAddress: UtilsCpp.getDisplayName(call.core.localAddress) + text: qsTr("Appel entrant%1").arg(localAddress ? qsTr(" pour %1").arg(localAddress.value) : "") //call.core.peerAddress + color: DefaultStyle.grey_600 + font { + pixelSize: 13 * DefaultStyle.dp + weight: 400 * DefaultStyle.dp + } + } } } } - + RowLayout { - Layout.fillHeight: true - Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter - spacing: 10 * DefaultStyle.dp - Item { - Layout.fillWidth: true - Layout.fillHeight: true - } - RowLayout { - Layout.alignment: Qt.AlignHCenter - spacing: 3 * DefaultStyle.dp - Button { - color: DefaultStyle.success_500main - Layout.preferredWidth: 40 * DefaultStyle.dp - Layout.preferredHeight: 40 * DefaultStyle.dp - contentItem: EffectImage { - colorizationColor: DefaultStyle.grey_0 - imageSource: AppIcons.phone - imageWidth: 24 * DefaultStyle.dp - imageHeight: 24 * DefaultStyle.dp - } - onClicked: { - mainItem.call.core.lAccept(false) - UtilsCpp.openCallsWindow(mainItem.call) - } + Layout.fillWidth: true + spacing: 26 * DefaultStyle.dp + Button { + color: DefaultStyle.success_500main + Layout.preferredWidth: 75 * DefaultStyle.dp + Layout.preferredHeight: 55 * DefaultStyle.dp + contentItem: EffectImage { + colorizationColor: DefaultStyle.grey_0 + imageSource: AppIcons.phone + imageWidth: 32 * DefaultStyle.dp + imageHeight: 32 * DefaultStyle.dp } - Button { - color: DefaultStyle.success_500main - Layout.preferredWidth: 40 * DefaultStyle.dp - Layout.preferredHeight: 40 * DefaultStyle.dp - contentItem: EffectImage { - colorizationColor: DefaultStyle.grey_0 - imageSource: AppIcons.videoCamera - imageWidth: 24 * DefaultStyle.dp - imageHeight: 24 * DefaultStyle.dp - } - onClicked: { - mainItem.call.core.lAccept(true) - UtilsCpp.openCallsWindow(mainItem.call) - } + onClicked: { + mainItem.call.core.lAccept(false) + UtilsCpp.openCallsWindow(mainItem.call) } } - Item{ - Layout.fillWidth: true - Layout.fillHeight: true - } Button { color: DefaultStyle.danger_500main - Layout.rightMargin: 20 * DefaultStyle.dp - Layout.preferredWidth: 55 * DefaultStyle.dp - Layout.preferredHeight: 40 * DefaultStyle.dp + Layout.preferredWidth: 75 * DefaultStyle.dp + Layout.preferredHeight: 55 * DefaultStyle.dp contentItem: EffectImage { colorizationColor: DefaultStyle.grey_0 imageSource: AppIcons.endCall - imageWidth: 24 * DefaultStyle.dp - imageHeight: 24 * DefaultStyle.dp + imageWidth: 32 * DefaultStyle.dp + imageHeight: 32 * DefaultStyle.dp } onClicked: { mainItem.call.core.lDecline() diff --git a/Linphone/view/Item/TextField.qml b/Linphone/view/Item/TextField.qml index 5218ecaa0..38053c519 100644 --- a/Linphone/view/Item/TextField.qml +++ b/Linphone/view/Item/TextField.qml @@ -10,6 +10,7 @@ Control.TextField { leftPadding: 15 * DefaultStyle.dp rightPadding: eyeButton.visible ? 5 * DefaultStyle.dp + eyeButton.width + eyeButton.rightMargin : 15 * DefaultStyle.dp echoMode: (hidden && !eyeButton.checked) ? TextInput.Password : TextInput.Normal + verticalAlignment: TextInput.AlignVCenter color: DefaultStyle.main2_600 font { family: DefaultStyle.defaultFont @@ -47,10 +48,12 @@ Control.TextField { ? DefaultStyle.main1_500_main : mainItem.backgroundBorderColor } + cursorDelegate: Rectangle { id: cursor color: DefaultStyle.main1_500_main width: 1 * DefaultStyle.dp + anchors.verticalCenter: mainItem.verticalCenter SequentialAnimation { loops: Animation.Infinite diff --git a/Linphone/view/Item/VerticalTabBar.qml b/Linphone/view/Item/VerticalTabBar.qml index 10d165b09..7b7a2f855 100644 --- a/Linphone/view/Item/VerticalTabBar.qml +++ b/Linphone/view/Item/VerticalTabBar.qml @@ -13,6 +13,11 @@ Control.TabBar { property var model readonly property alias cornerRadius: bottomLeftCorner.radius + property AccountGui defaultAccount + onDefaultAccountChanged: { + defaultAccount.core.lRefreshNotifications() + } + component UnreadNotification: Rectangle { id: unreadNotifications property int unread: 0 @@ -82,7 +87,7 @@ Control.TabBar { width: mainItem.width UnreadNotification { - unread: modelData.unreadNotifications + unread: index == 0 ? defaultAccount.core.unreadCallNotifications : index == 2 ? defaultAccount.core.unreadMessageNotifications : 0// modelData.unreadNotifications anchors.right: parent.right anchors.rightMargin: 15 * DefaultStyle.dp anchors.top: parent.top diff --git a/Linphone/view/Page/Main/ContactPage.qml b/Linphone/view/Page/Main/ContactPage.qml index 1798c0f54..952ce5490 100644 --- a/Linphone/view/Page/Main/ContactPage.qml +++ b/Linphone/view/Page/Main/ContactPage.qml @@ -549,7 +549,13 @@ AbstractMainPage { iconSize: 24 * DefaultStyle.dp iconSource: AppIcons.shareNetwork text: qsTr("Share") - onClicked: console.log("TODO : share contact") + onClicked: { + if (mainItem.selectedContact) { + var vcard = mainItem.selectedContact.core.getVCard() + UtilsCpp.copyToClipboard(vcard) + UtilsCpp.showInformationPopup(qsTr("Copié"), qsTr("VCard copiée dans le presse-papier")) + } + } } Rectangle { Layout.fillWidth: true