From a8339bebc35b8cc18ad824e69f1784df30e0125b Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 12 May 2022 19:56:11 +0200 Subject: [PATCH] Timezones and prepare conference view with them. Fix ICS views (better filterring). Factorization of isMe() to test lcoal address. New ComboBox design with better scrolling (like phone numbers in creation page). --- linphone-app/CMakeLists.txt | 6 + linphone-app/src/app/App.cpp | 2 +- linphone-app/src/components/Components.hpp | 3 + .../chat-events/ChatMessageModel.cpp | 2 +- .../components/chat-room/ChatRoomModel.cpp | 2 +- .../conferenceInfo/ConferenceInfoModel.cpp | 8 +- .../ConferenceInfoProxyListModel.cpp | 9 +- .../components/content/ContentListModel.cpp | 2 +- .../src/components/core/CoreHandlers.cpp | 2 +- .../src/components/ldap/LdapListModel.cpp | 2 +- .../other/timeZone/TimeZoneListModel.cpp | 83 +++ .../other/timeZone/TimeZoneListModel.hpp | 43 ++ .../other/timeZone/TimeZoneModel.cpp | 56 ++ .../other/timeZone/TimeZoneModel.hpp | 54 ++ .../other/timeZone/TimeZoneProxyModel.cpp | 62 +++ .../other/timeZone/TimeZoneProxyModel.hpp | 41 ++ .../participant/ParticipantModel.cpp | 3 +- .../TelephoneNumbersModel.cpp | 499 +++++++++--------- linphone-app/src/utils/Utils.cpp | 11 +- linphone-app/src/utils/Utils.hpp | 4 + .../ui/modules/Common/Form/ComboBox.qml | 206 +++++--- .../Common/Form/CommonItemDelegate.qml | 134 +++-- .../Form/Fields/ScrollableListViewField.qml | 10 +- .../modules/Common/Form/ListItemSelector.qml | 72 +-- .../modules/Linphone/Chat/ChatDeliveries.qml | 4 +- .../Linphone/Menus/SipAddressesMenu.qml | 2 +- .../ui/views/App/Dialog/NewConference.qml | 46 +- .../CreateAppSipAccountWithPhoneNumber.qml | 6 +- linphone-sdk | 2 +- 29 files changed, 902 insertions(+), 474 deletions(-) create mode 100644 linphone-app/src/components/other/timeZone/TimeZoneListModel.cpp create mode 100644 linphone-app/src/components/other/timeZone/TimeZoneListModel.hpp create mode 100644 linphone-app/src/components/other/timeZone/TimeZoneModel.cpp create mode 100644 linphone-app/src/components/other/timeZone/TimeZoneModel.hpp create mode 100644 linphone-app/src/components/other/timeZone/TimeZoneProxyModel.cpp create mode 100644 linphone-app/src/components/other/timeZone/TimeZoneProxyModel.hpp diff --git a/linphone-app/CMakeLists.txt b/linphone-app/CMakeLists.txt index a51218f9e..1153d3405 100644 --- a/linphone-app/CMakeLists.txt +++ b/linphone-app/CMakeLists.txt @@ -209,6 +209,9 @@ set(SOURCES src/components/other/images/ImageListModel.cpp src/components/other/images/ImageProxyModel.cpp src/components/other/text-to-speech/TextToSpeech.cpp + src/components/other/timeZone/TimeZoneModel.cpp + src/components/other/timeZone/TimeZoneListModel.cpp + src/components/other/timeZone/TimeZoneProxyModel.cpp src/components/other/units/Units.cpp src/components/participant/ParticipantModel.cpp src/components/participant/ParticipantListModel.cpp @@ -342,6 +345,9 @@ set(HEADERS src/components/other/images/ImageProxyModel.hpp src/components/other/desktop-tools/DesktopTools.hpp src/components/other/text-to-speech/TextToSpeech.hpp + src/components/other/timeZone/TimeZoneModel.hpp + src/components/other/timeZone/TimeZoneListModel.hpp + src/components/other/timeZone/TimeZoneProxyModel.hpp src/components/other/units/Units.hpp src/components/participant/ParticipantModel.hpp src/components/participant/ParticipantListModel.hpp diff --git a/linphone-app/src/app/App.cpp b/linphone-app/src/app/App.cpp index 69dccb9a6..b1dda3fd7 100644 --- a/linphone-app/src/app/App.cpp +++ b/linphone-app/src/app/App.cpp @@ -645,7 +645,7 @@ void App::registerTypes () { registerType("SipAddressesProxyModel"); registerType("SearchSipAddressesModel"); registerType("SearchSipAddressesProxyModel"); - + registerType("TimeZoneProxyModel"); registerType("ColorProxyModel"); registerType("ImageColorsProxyModel"); diff --git a/linphone-app/src/components/Components.hpp b/linphone-app/src/components/Components.hpp index be73712a9..a8618b035 100644 --- a/linphone-app/src/components/Components.hpp +++ b/linphone-app/src/components/Components.hpp @@ -101,6 +101,9 @@ #include "other/images/ImageListModel.hpp" #include "other/images/ImageProxyModel.hpp" #include "other/text-to-speech/TextToSpeech.hpp" +#include "other/timeZone/TimeZoneModel.hpp" +#include "other/timeZone/TimeZoneListModel.hpp" +#include "other/timeZone/TimeZoneProxyModel.hpp" #include "other/units/Units.hpp" #endif // COMPONENTS_H_ diff --git a/linphone-app/src/components/chat-events/ChatMessageModel.cpp b/linphone-app/src/components/chat-events/ChatMessageModel.cpp index 8d43df554..5b5290312 100644 --- a/linphone-app/src/components/chat-events/ChatMessageModel.cpp +++ b/linphone-app/src/components/chat-events/ChatMessageModel.cpp @@ -215,7 +215,7 @@ QString ChatMessageModel::getForwardInfo() const{ QString ChatMessageModel::getForwardInfoDisplayName() const{ QString forwardInfo = getForwardInfo(); auto forwardAddress = Utils::interpretUrl(forwardInfo); - if(!forwardAddress || CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress()->weakEqual(forwardAddress)) + if(!forwardAddress || Utils::isMe(forwardAddress)) return "";// myself else return Utils::getDisplayName(forwardInfo); diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.cpp b/linphone-app/src/components/chat-room/ChatRoomModel.cpp index 90b45831e..9ef5714f4 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.cpp @@ -435,7 +435,7 @@ bool ChatRoomModel::isMeAdmin() const{ } bool ChatRoomModel::isCurrentAccount() const{ - return mChatRoom->getLocalAddress()->weakEqual(CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress()); + return Utils::isMe(mChatRoom->getLocalAddress()); } bool ChatRoomModel::canHandleParticipants() const{ diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp index 36f95c53c..bcb85f053 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp @@ -80,6 +80,9 @@ QSharedPointer ConferenceInfoModel::create(std::shared_ptr< ConferenceInfoModel::ConferenceInfoModel (QObject * parent) : QObject(parent){ //App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE mConferenceInfo = linphone::Factory::get()->createConferenceInfo(); + mConferenceInfo->setDateTime(QDateTime::currentMSecsSinceEpoch() / 1000 + 60); + mConferenceInfo->setDuration(1200); + mIsScheduled = true; auto accountAddress = CoreManager::getInstance()->getCore()->getDefaultAccount()->getContactAddress(); accountAddress->clean(); mConferenceInfo->setOrganizer(accountAddress); @@ -89,6 +92,8 @@ ConferenceInfoModel::ConferenceInfoModel (std::shared_ptrgetEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE mConferenceInfo = conferenceInfo; + //mIsScheduled = getDateTime() >= QDateTime::currentDateTime(); + mIsScheduled = true; } ConferenceInfoModel::~ConferenceInfoModel () { @@ -140,7 +145,8 @@ QString ConferenceInfoModel::displayNamesToString()const{ } QString ConferenceInfoModel::getUri() const{ - return QString::fromStdString(mConferenceInfo->getUri()->asString()); + auto address = mConferenceInfo->getUri(); + return address->isValid() && !address->getDomain().empty() ? QString::fromStdString(address->asString()) : ""; } bool ConferenceInfoModel::isScheduled() const{ diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyListModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyListModel.cpp index 2e1c096e3..a78c23486 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyListModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyListModel.cpp @@ -26,6 +26,8 @@ #include "ConferenceInfoListModel.hpp" #include "ConferenceInfoMapModel.hpp" +#include "utils/Utils.hpp" + // ============================================================================= @@ -48,8 +50,11 @@ bool ConferenceInfoProxyListModel::filterAcceptsRow (int sourceRow, const QModel if( mFilterType == 0){ return ics->getEndDateTime() < currentDateTime; }else if( mFilterType == 1){ - return ics->getDateTime() >= currentDateTime; - } + return ics->getEndDateTime() >= currentDateTime; + }else if( mFilterType == 2){ + return !Utils::isMe(ics->getOrganizer()); + }else + return mFilterType == -1; } } return true; diff --git a/linphone-app/src/components/content/ContentListModel.cpp b/linphone-app/src/components/content/ContentListModel.cpp index 04a28f2cf..e15214ab8 100644 --- a/linphone-app/src/components/content/ContentListModel.cpp +++ b/linphone-app/src/components/content/ContentListModel.cpp @@ -151,7 +151,7 @@ void ContentListModel::updateContents(ChatMessageModel * messageModel){ while( c < mList.size() && mList.at(c).objectCast()->getContent() != content) ++c; if( c < mList.size()){// Found => swap position - mList.swap(count, c); + mList.swapItemsAt(count, c); }else{// content is new mList.insert(count, QSharedPointer::create(content, messageModel)); } diff --git a/linphone-app/src/components/core/CoreHandlers.cpp b/linphone-app/src/components/core/CoreHandlers.cpp index 2dc4af776..e21ceb9f3 100644 --- a/linphone-app/src/components/core/CoreHandlers.cpp +++ b/linphone-app/src/components/core/CoreHandlers.cpp @@ -220,7 +220,7 @@ void CoreHandlers::onMessageReceived ( // 2. Notify with Notification popup. const App *app = App::getInstance(); - if (coreManager->getSettingsModel()->getChatNotificationsEnabled() && (!app->hasFocus() || !chatRoom->getLocalAddress()->weakEqual(coreManager->getAccountSettingsModel()->getUsedSipAddress()))) + if (coreManager->getSettingsModel()->getChatNotificationsEnabled() && (!app->hasFocus() || !Utils::isMe(chatRoom->getLocalAddress()))) app->getNotifier()->notifyReceivedMessage(message); // 3. Notify with sound. diff --git a/linphone-app/src/components/ldap/LdapListModel.cpp b/linphone-app/src/components/ldap/LdapListModel.cpp index 5ffe04947..161e7382a 100644 --- a/linphone-app/src/components/ldap/LdapListModel.cpp +++ b/linphone-app/src/components/ldap/LdapListModel.cpp @@ -39,7 +39,6 @@ LdapListModel::LdapListModel (QObject *parent) : ProxyListModel(parent) { // ----------------------------------------------------------------------------- void LdapListModel::reset(){ - resetInternalData(); initLdap(); } @@ -49,6 +48,7 @@ void LdapListModel::reset(){ void LdapListModel::initLdap () { CoreManager *coreManager = CoreManager::getInstance(); auto ldapList = coreManager->getCore()->getLdapList(); + resetData(); for(auto ldap : ldapList){ ProxyListModel::add(QSharedPointer::create(ldap)); } diff --git a/linphone-app/src/components/other/timeZone/TimeZoneListModel.cpp b/linphone-app/src/components/other/timeZone/TimeZoneListModel.cpp new file mode 100644 index 000000000..c5b5a97cc --- /dev/null +++ b/linphone-app/src/components/other/timeZone/TimeZoneListModel.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TimeZoneListModel.hpp" + +#include + +// ============================================================================= + +using namespace std; + +TimeZoneListModel::TimeZoneListModel (QObject *parent) : ProxyListModel(parent) { + initTimeZones(); +} + +// ----------------------------------------------------------------------------- + +void TimeZoneListModel::initTimeZones () { + resetData(); + for(auto id : QTimeZone::availableTimeZoneIds()){ + auto model = QSharedPointer::create(QTimeZone(id)); + if(model->getCountryName().toUpper() != "DEFAULT") + ProxyListModel::add(model); + } +} + + +QHash TimeZoneListModel::roleNames () const { + QHash roles; + roles[Qt::DisplayRole] = "$modelData"; + roles[Qt::DisplayRole+1] = "displayText"; + return roles; +} + +QVariant TimeZoneListModel::data (const QModelIndex &index, int role) const { + int row = index.row(); + + if (!index.isValid() || row < 0 || row >= mList.count()) + return QVariant(); + auto timeZoneModel = getAt(row); + if (role == Qt::DisplayRole) { + return QVariant::fromValue(timeZoneModel.get()); + }else{ + int offset = timeZoneModel->getStandardTimeOffset()/3600; + int absOffset = std::abs(offset); + + return QStringLiteral("%1 (UTC%2%3%4) %5") + .arg(timeZoneModel->getCountryName()) + .arg(offset >=0 ? "+" : "-") + .arg(absOffset <10 ? "0" : "") + .arg(absOffset) + .arg(timeZoneModel->getTimeZone().comment()); + } + + return QVariant(); +} + +int TimeZoneListModel::getDefaultIndex () const { + auto defaultTimezone = QTimeZone::systemTimeZone(); + const auto it = find_if( + mList.cbegin(), mList.cend(), [&defaultTimezone](QSharedPointer item) { + return item.objectCast()->getTimeZone() == defaultTimezone; + } + ); + return it != mList.cend() ? int(distance(mList.cbegin(), it)) : 0; +} \ No newline at end of file diff --git a/linphone-app/src/components/other/timeZone/TimeZoneListModel.hpp b/linphone-app/src/components/other/timeZone/TimeZoneListModel.hpp new file mode 100644 index 000000000..226f34b8a --- /dev/null +++ b/linphone-app/src/components/other/timeZone/TimeZoneListModel.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef TIME_ZONE_LIST_MODEL_H_ +#define TIME_ZONE_LIST_MODEL_H_ + +#include "TimeZoneModel.hpp" +#include "app/proxyModel/ProxyListModel.hpp" +// ============================================================================= + +class TimeZoneListModel : public ProxyListModel { + Q_OBJECT + +public: + + TimeZoneListModel (QObject *parent = Q_NULLPTR); + + void initTimeZones(); + int getDefaultIndex () const; + + QHash roleNames () const override; + QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override; + +}; + +#endif diff --git a/linphone-app/src/components/other/timeZone/TimeZoneModel.cpp b/linphone-app/src/components/other/timeZone/TimeZoneModel.cpp new file mode 100644 index 000000000..7540b394f --- /dev/null +++ b/linphone-app/src/components/other/timeZone/TimeZoneModel.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TimeZoneModel.hpp" + +#include "app/App.hpp" +#include "utils/Utils.hpp" + +#include + +// ============================================================================= + +TimeZoneModel::TimeZoneModel (const QTimeZone& timeZone, QObject *parent ) : QObject(parent){ + App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE + mTimeZone = timeZone; +} + +TimeZoneModel::~TimeZoneModel(){ +} + +QTimeZone TimeZoneModel::getTimeZone()const{ + return mTimeZone; +} + +int TimeZoneModel::getOffsetFromUtc() const{ + return mTimeZone.offsetFromUtc(QDateTime::currentDateTime()); +} + +int TimeZoneModel::getStandardTimeOffset() const{ + return mTimeZone.standardTimeOffset(QDateTime::currentDateTime()); +} + +QString TimeZoneModel::getCountryName() const{ + return Utils::getCountryName(mTimeZone.country()); +} + +QString TimeZoneModel::getDisplayName() const{ + return mTimeZone.displayName(QTimeZone::TimeType::GenericTime); +} \ No newline at end of file diff --git a/linphone-app/src/components/other/timeZone/TimeZoneModel.hpp b/linphone-app/src/components/other/timeZone/TimeZoneModel.hpp new file mode 100644 index 000000000..0498c6bb3 --- /dev/null +++ b/linphone-app/src/components/other/timeZone/TimeZoneModel.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef TIME_ZONE_MODEL_H_ +#define TIME_ZONE_MODEL_H_ + +#include +#include + +#include + +// ============================================================================= + +class TimeZoneModel : public QObject { + Q_OBJECT + Q_PROPERTY(QTimeZone timezone MEMBER mTimeZone CONSTANT) + Q_PROPERTY(int offsetFromUtc READ getOffsetFromUtc CONSTANT) + Q_PROPERTY(int standardTimeOffset READ getStandardTimeOffset CONSTANT) + Q_PROPERTY(QString countryName READ getCountryName CONSTANT) + Q_PROPERTY(QString displayName READ getDisplayName CONSTANT) + +public: + + TimeZoneModel (const QTimeZone& timeZone, QObject *parent = nullptr); + virtual ~TimeZoneModel(); + + QTimeZone getTimeZone()const; + int getOffsetFromUtc() const; + int getStandardTimeOffset() const; + QString getCountryName() const; + QString getDisplayName() const; + +private: + QTimeZone mTimeZone; +}; +Q_DECLARE_METATYPE(TimeZoneModel*); +#endif diff --git a/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.cpp b/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.cpp new file mode 100644 index 000000000..3baa2639f --- /dev/null +++ b/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "components/core/CoreManager.hpp" + +#include "TimeZoneModel.hpp" +#include "TimeZoneListModel.hpp" +#include "TimeZoneProxyModel.hpp" + +// ----------------------------------------------------------------------------- + +TimeZoneProxyModel::TimeZoneProxyModel (QObject *parent) : QSortFilterProxyModel(parent) { + setSourceModel(new TimeZoneListModel(parent)); + sort(0); +} + +// ----------------------------------------------------------------------------- + +bool TimeZoneProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const { + const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + return true; +} + +bool TimeZoneProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const { + auto test = sourceModel()->data(left); + const TimeZoneModel* a = sourceModel()->data(left).value(); + const TimeZoneModel* b = sourceModel()->data(right).value(); + auto timeA = a->getStandardTimeOffset(); + auto timeB = b->getStandardTimeOffset(); + +/* + const QVariantMap mapA = sourceModel()->data(left).value(); + const QVariantMap mapB = sourceModel()->data(right).value(); + const TimeZoneModel* a = mapA["timeZoneModel"].value(); + const TimeZoneModel* b = mapB["timeZoneModel"].value(); + auto timeA = a->getStandardTimeOffset(); + auto timeB = b->getStandardTimeOffset(); + */ + + return timeA < timeB || (timeA == timeB && a->getCountryName() < b->getCountryName()); +} + +int TimeZoneProxyModel::getDefaultIndex() const{ + return mapFromSource(sourceModel()->index(qobject_cast(sourceModel())->getDefaultIndex(), 0)).row(); +} diff --git a/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.hpp b/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.hpp new file mode 100644 index 000000000..0a645879b --- /dev/null +++ b/linphone-app/src/components/other/timeZone/TimeZoneProxyModel.hpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef TIME_ZONE_PROXY_MODEL_H_ +#define TIME_ZONE_PROXY_MODEL_H_ + +#include + +// ============================================================================= + +class TimeZoneProxyModel : public QSortFilterProxyModel { + Q_OBJECT +public: + TimeZoneProxyModel (QObject *parent = Q_NULLPTR); + Q_PROPERTY(int defaultIndex READ getDefaultIndex CONSTANT) + + int getDefaultIndex() const; + +protected: + bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override; + bool lessThan (const QModelIndex &left, const QModelIndex &right) const override; +}; + +#endif diff --git a/linphone-app/src/components/participant/ParticipantModel.cpp b/linphone-app/src/components/participant/ParticipantModel.cpp index 9a19730a5..3e1b7cead 100644 --- a/linphone-app/src/components/participant/ParticipantModel.cpp +++ b/linphone-app/src/components/participant/ParticipantModel.cpp @@ -65,8 +65,7 @@ bool ParticipantModel::getInviting() const{ } bool ParticipantModel::isMe() const{ - QString sipAddress = getSipAddress(); - return !sipAddress.isEmpty() ? CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress()->weakEqual(Utils::interpretUrl(sipAddress)) : false; + return Utils::isMe(getSipAddress()); } QString ParticipantModel::getSipAddress() const{ diff --git a/linphone-app/src/components/telephone-numbers/TelephoneNumbersModel.cpp b/linphone-app/src/components/telephone-numbers/TelephoneNumbersModel.cpp index 80154291f..64c4eb474 100644 --- a/linphone-app/src/components/telephone-numbers/TelephoneNumbersModel.cpp +++ b/linphone-app/src/components/telephone-numbers/TelephoneNumbersModel.cpp @@ -26,229 +26,229 @@ using namespace std; const QList> TelephoneNumbersModel::mCountryCodes = { - { QLocale::Afghanistan, "93" }, - { QLocale::Albania, "355" }, - { QLocale::Algeria, "213" }, - { QLocale::AmericanSamoa, "1" }, - { QLocale::Andorra, "376" }, - { QLocale::Angola, "244" }, - { QLocale::Anguilla, "1" }, - { QLocale::AntiguaAndBarbuda, "1" }, - { QLocale::Argentina, "54" }, - { QLocale::Armenia, "374" }, - { QLocale::Aruba, "297" }, - { QLocale::Australia, "61" }, - { QLocale::Austria, "43" }, - { QLocale::Azerbaijan, "994" }, - { QLocale::Bahamas, "1" }, - { QLocale::Bahrain, "973" }, - { QLocale::Bangladesh, "880" }, - { QLocale::Barbados, "1" }, - { QLocale::Belarus, "375" }, - { QLocale::Belgium, "32" }, - { QLocale::Belize, "501" }, - { QLocale::Benin, "229" }, - { QLocale::Bermuda, "1" }, - { QLocale::Bhutan, "975" }, - { QLocale::Bolivia, "591" }, - { QLocale::BosniaAndHerzegowina, "387" }, - { QLocale::Botswana, "267" }, - { QLocale::Brazil, "55" }, - { QLocale::Brunei, "673" }, - { QLocale::Bulgaria, "359" }, - { QLocale::BurkinaFaso, "226" }, - { QLocale::Burundi, "257" }, - { QLocale::Cambodia, "855" }, - { QLocale::Cameroon, "237" }, - { QLocale::Canada, "1" }, - { QLocale::CapeVerde, "238" }, - { QLocale::CaymanIslands, "1" }, - { QLocale::CentralAfricanRepublic, "236" }, - { QLocale::Chad, "235" }, - { QLocale::Chile, "56" }, - { QLocale::China, "86" }, - { QLocale::Colombia, "57" }, - { QLocale::Comoros, "269" }, - { QLocale::PeoplesRepublicOfCongo, "242" }, - { QLocale::DemocraticRepublicOfCongo, "243" }, - { QLocale::CookIslands, "682" }, - { QLocale::CostaRica, "506" }, - { QLocale::IvoryCoast, "225" }, - { QLocale::Croatia, "385" }, - { QLocale::Cuba, "53" }, - { QLocale::Cyprus, "357" }, - { QLocale::CzechRepublic, "420" }, - { QLocale::Denmark, "45" }, - { QLocale::Djibouti, "253" }, - { QLocale::Dominica, "1" }, - { QLocale::DominicanRepublic, "1" }, - { QLocale::Ecuador, "593" }, - { QLocale::Egypt, "20" }, - { QLocale::ElSalvador, "503" }, - { QLocale::EquatorialGuinea, "240" }, - { QLocale::Eritrea, "291" }, - { QLocale::Estonia, "372" }, - { QLocale::Ethiopia, "251" }, - { QLocale::FalklandIslands, "500" }, - { QLocale::FaroeIslands, "298" }, - { QLocale::Fiji, "679" }, - { QLocale::Finland, "358" }, - { QLocale::France, "33" }, - { QLocale::FrenchGuiana, "594" }, - { QLocale::FrenchPolynesia, "689" }, - { QLocale::Gabon, "241" }, - { QLocale::Gambia, "220" }, - { QLocale::Georgia, "995" }, - { QLocale::Germany, "49" }, - { QLocale::Ghana, "233" }, - { QLocale::Gibraltar, "350" }, - { QLocale::Greece, "30" }, - { QLocale::Greenland, "299" }, - { QLocale::Grenada, "1" }, - { QLocale::Guadeloupe, "590" }, - { QLocale::Guam, "1" }, - { QLocale::Guatemala, "502" }, - { QLocale::Guinea, "224" }, - { QLocale::GuineaBissau, "245" }, - { QLocale::Guyana, "592" }, - { QLocale::Haiti, "509" }, - { QLocale::Honduras, "504" }, - { QLocale::HongKong, "852" }, - { QLocale::Hungary, "36" }, - { QLocale::Iceland, "354" }, - { QLocale::India, "91" }, - { QLocale::Indonesia, "62" }, - { QLocale::Iran, "98" }, - { QLocale::Iraq, "964" }, - { QLocale::Ireland, "353" }, - { QLocale::Israel, "972" }, - { QLocale::Italy, "39" }, - { QLocale::Jamaica, "1" }, - { QLocale::Japan, "81" }, - { QLocale::Jordan, "962" }, - { QLocale::Kazakhstan, "7" }, - { QLocale::Kenya, "254" }, - { QLocale::Kiribati, "686" }, - { QLocale::DemocraticRepublicOfKorea, "850" }, - { QLocale::RepublicOfKorea, "82" }, - { QLocale::Kuwait, "965" }, - { QLocale::Kyrgyzstan, "996" }, - { QLocale::Laos, "856" }, - { QLocale::Latvia, "371" }, - { QLocale::Lebanon, "961" }, - { QLocale::Lesotho, "266" }, - { QLocale::Liberia, "231" }, - { QLocale::Libya, "218" }, - { QLocale::Liechtenstein, "423" }, - { QLocale::Lithuania, "370" }, - { QLocale::Luxembourg, "352" }, - { QLocale::Macau, "853" }, - { QLocale::Macedonia, "389" }, - { QLocale::Madagascar, "261" }, - { QLocale::Malawi, "265" }, - { QLocale::Malaysia, "60" }, - { QLocale::Maldives, "960" }, - { QLocale::Mali, "223" }, - { QLocale::Malta, "356" }, - { QLocale::MarshallIslands, "692" }, - { QLocale::Martinique, "596" }, - { QLocale::Mauritania, "222" }, - { QLocale::Mauritius, "230" }, - { QLocale::Mayotte, "262" }, - { QLocale::Mexico, "52" }, - { QLocale::Micronesia, "691" }, - { QLocale::Moldova, "373" }, - { QLocale::Monaco, "377" }, - { QLocale::Mongolia, "976" }, - { QLocale::Montenegro, "382" }, - { QLocale::Montserrat, "664" }, - { QLocale::Morocco, "212" }, - { QLocale::Mozambique, "258" }, - { QLocale::Myanmar, "95" }, - { QLocale::Namibia, "264" }, - { QLocale::NauruCountry, "674" }, - { QLocale::Nepal, "43" }, - { QLocale::Netherlands, "31" }, - { QLocale::NewCaledonia, "687" }, - { QLocale::NewZealand, "64" }, - { QLocale::Nicaragua, "505" }, - { QLocale::Niger, "227" }, - { QLocale::Nigeria, "234" }, - { QLocale::Niue, "683" }, - { QLocale::NorfolkIsland, "672" }, - { QLocale::NorthernMarianaIslands, "1" }, - { QLocale::Norway, "47" }, - { QLocale::Oman, "968" }, - { QLocale::Pakistan, "92" }, - { QLocale::Palau, "680" }, - { QLocale::PalestinianTerritories, "970" }, - { QLocale::Panama, "507" }, - { QLocale::PapuaNewGuinea, "675" }, - { QLocale::Paraguay, "595" }, - { QLocale::Peru, "51" }, - { QLocale::Philippines, "63" }, - { QLocale::Poland, "48" }, - { QLocale::Portugal, "351" }, - { QLocale::PuertoRico, "1" }, - { QLocale::Qatar, "974" }, - { QLocale::Reunion, "262" }, - { QLocale::Romania, "40" }, - { QLocale::RussianFederation, "7" }, - { QLocale::Rwanda, "250" }, - { QLocale::SaintHelena, "290" }, - { QLocale::SaintKittsAndNevis, "1" }, - { QLocale::SaintLucia, "1" }, - { QLocale::SaintPierreAndMiquelon, "508" }, - { QLocale::SaintVincentAndTheGrenadines, "1" }, - { QLocale::Samoa, "685" }, - { QLocale::SanMarino, "378" }, - { QLocale::SaoTomeAndPrincipe, "239" }, - { QLocale::SaudiArabia, "966" }, - { QLocale::Senegal, "221" }, - { QLocale::Serbia, "381" }, - { QLocale::Seychelles, "248" }, - { QLocale::SierraLeone, "232" }, - { QLocale::Singapore, "65" }, - { QLocale::Slovakia, "421" }, - { QLocale::Slovenia, "386" }, - { QLocale::SolomonIslands, "677" }, - { QLocale::Somalia, "252" }, - { QLocale::SouthAfrica, "27" }, - { QLocale::Spain, "34" }, - { QLocale::SriLanka, "94" }, - { QLocale::Sudan, "249" }, - { QLocale::Suriname, "597" }, - { QLocale::Swaziland, "268" }, - { QLocale::Sweden, "46" }, - { QLocale::Switzerland, "41" }, - { QLocale::Syria, "963" }, - { QLocale::Taiwan, "886" }, - { QLocale::Tajikistan, "992" }, - { QLocale::Tanzania, "255" }, - { QLocale::Thailand, "66" }, - { QLocale::Togo, "228" }, - { QLocale::Tokelau, "690" }, - { QLocale::Tonga, "676" }, - { QLocale::TrinidadAndTobago, "1" }, - { QLocale::Tunisia, "216" }, - { QLocale::Turkey, "90" }, - { QLocale::Turkmenistan, "993" }, - { QLocale::TurksAndCaicosIslands, "1" }, - { QLocale::Tuvalu, "688" }, - { QLocale::Uganda, "256" }, - { QLocale::Ukraine, "380" }, - { QLocale::UnitedArabEmirates, "971" }, - { QLocale::UnitedKingdom, "44" }, - { QLocale::UnitedStates, "1" }, - { QLocale::Uruguay, "598" }, - { QLocale::Uzbekistan, "998" }, - { QLocale::Vanuatu, "678" }, - { QLocale::Venezuela, "58" }, - { QLocale::Vietnam, "84" }, - { QLocale::WallisAndFutunaIslands, "681" }, - { QLocale::Yemen, "967" }, - { QLocale::Zambia, "260" }, - { QLocale::Zimbabwe, "263" } + { QLocale::Afghanistan, "93" }, + { QLocale::Albania, "355" }, + { QLocale::Algeria, "213" }, + { QLocale::AmericanSamoa, "1" }, + { QLocale::Andorra, "376" }, + { QLocale::Angola, "244" }, + { QLocale::Anguilla, "1" }, + { QLocale::AntiguaAndBarbuda, "1" }, + { QLocale::Argentina, "54" }, + { QLocale::Armenia, "374" }, + { QLocale::Aruba, "297" }, + { QLocale::Australia, "61" }, + { QLocale::Austria, "43" }, + { QLocale::Azerbaijan, "994" }, + { QLocale::Bahamas, "1" }, + { QLocale::Bahrain, "973" }, + { QLocale::Bangladesh, "880" }, + { QLocale::Barbados, "1" }, + { QLocale::Belarus, "375" }, + { QLocale::Belgium, "32" }, + { QLocale::Belize, "501" }, + { QLocale::Benin, "229" }, + { QLocale::Bermuda, "1" }, + { QLocale::Bhutan, "975" }, + { QLocale::Bolivia, "591" }, + { QLocale::BosniaAndHerzegowina, "387" }, + { QLocale::Botswana, "267" }, + { QLocale::Brazil, "55" }, + { QLocale::Brunei, "673" }, + { QLocale::Bulgaria, "359" }, + { QLocale::BurkinaFaso, "226" }, + { QLocale::Burundi, "257" }, + { QLocale::Cambodia, "855" }, + { QLocale::Cameroon, "237" }, + { QLocale::Canada, "1" }, + { QLocale::CapeVerde, "238" }, + { QLocale::CaymanIslands, "1" }, + { QLocale::CentralAfricanRepublic, "236" }, + { QLocale::Chad, "235" }, + { QLocale::Chile, "56" }, + { QLocale::China, "86" }, + { QLocale::Colombia, "57" }, + { QLocale::Comoros, "269" }, + { QLocale::PeoplesRepublicOfCongo, "242" }, + { QLocale::DemocraticRepublicOfCongo, "243" }, + { QLocale::CookIslands, "682" }, + { QLocale::CostaRica, "506" }, + { QLocale::IvoryCoast, "225" }, + { QLocale::Croatia, "385" }, + { QLocale::Cuba, "53" }, + { QLocale::Cyprus, "357" }, + { QLocale::CzechRepublic, "420" }, + { QLocale::Denmark, "45" }, + { QLocale::Djibouti, "253" }, + { QLocale::Dominica, "1" }, + { QLocale::DominicanRepublic, "1" }, + { QLocale::Ecuador, "593" }, + { QLocale::Egypt, "20" }, + { QLocale::ElSalvador, "503" }, + { QLocale::EquatorialGuinea, "240" }, + { QLocale::Eritrea, "291" }, + { QLocale::Estonia, "372" }, + { QLocale::Ethiopia, "251" }, + { QLocale::FalklandIslands, "500" }, + { QLocale::FaroeIslands, "298" }, + { QLocale::Fiji, "679" }, + { QLocale::Finland, "358" }, + { QLocale::France, "33" }, + { QLocale::FrenchGuiana, "594" }, + { QLocale::FrenchPolynesia, "689" }, + { QLocale::Gabon, "241" }, + { QLocale::Gambia, "220" }, + { QLocale::Georgia, "995" }, + { QLocale::Germany, "49" }, + { QLocale::Ghana, "233" }, + { QLocale::Gibraltar, "350" }, + { QLocale::Greece, "30" }, + { QLocale::Greenland, "299" }, + { QLocale::Grenada, "1" }, + { QLocale::Guadeloupe, "590" }, + { QLocale::Guam, "1" }, + { QLocale::Guatemala, "502" }, + { QLocale::Guinea, "224" }, + { QLocale::GuineaBissau, "245" }, + { QLocale::Guyana, "592" }, + { QLocale::Haiti, "509" }, + { QLocale::Honduras, "504" }, + { QLocale::HongKong, "852" }, + { QLocale::Hungary, "36" }, + { QLocale::Iceland, "354" }, + { QLocale::India, "91" }, + { QLocale::Indonesia, "62" }, + { QLocale::Iran, "98" }, + { QLocale::Iraq, "964" }, + { QLocale::Ireland, "353" }, + { QLocale::Israel, "972" }, + { QLocale::Italy, "39" }, + { QLocale::Jamaica, "1" }, + { QLocale::Japan, "81" }, + { QLocale::Jordan, "962" }, + { QLocale::Kazakhstan, "7" }, + { QLocale::Kenya, "254" }, + { QLocale::Kiribati, "686" }, + { QLocale::DemocraticRepublicOfKorea, "850" }, + { QLocale::RepublicOfKorea, "82" }, + { QLocale::Kuwait, "965" }, + { QLocale::Kyrgyzstan, "996" }, + { QLocale::Laos, "856" }, + { QLocale::Latvia, "371" }, + { QLocale::Lebanon, "961" }, + { QLocale::Lesotho, "266" }, + { QLocale::Liberia, "231" }, + { QLocale::Libya, "218" }, + { QLocale::Liechtenstein, "423" }, + { QLocale::Lithuania, "370" }, + { QLocale::Luxembourg, "352" }, + { QLocale::Macau, "853" }, + { QLocale::Macedonia, "389" }, + { QLocale::Madagascar, "261" }, + { QLocale::Malawi, "265" }, + { QLocale::Malaysia, "60" }, + { QLocale::Maldives, "960" }, + { QLocale::Mali, "223" }, + { QLocale::Malta, "356" }, + { QLocale::MarshallIslands, "692" }, + { QLocale::Martinique, "596" }, + { QLocale::Mauritania, "222" }, + { QLocale::Mauritius, "230" }, + { QLocale::Mayotte, "262" }, + { QLocale::Mexico, "52" }, + { QLocale::Micronesia, "691" }, + { QLocale::Moldova, "373" }, + { QLocale::Monaco, "377" }, + { QLocale::Mongolia, "976" }, + { QLocale::Montenegro, "382" }, + { QLocale::Montserrat, "664" }, + { QLocale::Morocco, "212" }, + { QLocale::Mozambique, "258" }, + { QLocale::Myanmar, "95" }, + { QLocale::Namibia, "264" }, + { QLocale::NauruCountry, "674" }, + { QLocale::Nepal, "43" }, + { QLocale::Netherlands, "31" }, + { QLocale::NewCaledonia, "687" }, + { QLocale::NewZealand, "64" }, + { QLocale::Nicaragua, "505" }, + { QLocale::Niger, "227" }, + { QLocale::Nigeria, "234" }, + { QLocale::Niue, "683" }, + { QLocale::NorfolkIsland, "672" }, + { QLocale::NorthernMarianaIslands, "1" }, + { QLocale::Norway, "47" }, + { QLocale::Oman, "968" }, + { QLocale::Pakistan, "92" }, + { QLocale::Palau, "680" }, + { QLocale::PalestinianTerritories, "970" }, + { QLocale::Panama, "507" }, + { QLocale::PapuaNewGuinea, "675" }, + { QLocale::Paraguay, "595" }, + { QLocale::Peru, "51" }, + { QLocale::Philippines, "63" }, + { QLocale::Poland, "48" }, + { QLocale::Portugal, "351" }, + { QLocale::PuertoRico, "1" }, + { QLocale::Qatar, "974" }, + { QLocale::Reunion, "262" }, + { QLocale::Romania, "40" }, + { QLocale::RussianFederation, "7" }, + { QLocale::Rwanda, "250" }, + { QLocale::SaintHelena, "290" }, + { QLocale::SaintKittsAndNevis, "1" }, + { QLocale::SaintLucia, "1" }, + { QLocale::SaintPierreAndMiquelon, "508" }, + { QLocale::SaintVincentAndTheGrenadines, "1" }, + { QLocale::Samoa, "685" }, + { QLocale::SanMarino, "378" }, + { QLocale::SaoTomeAndPrincipe, "239" }, + { QLocale::SaudiArabia, "966" }, + { QLocale::Senegal, "221" }, + { QLocale::Serbia, "381" }, + { QLocale::Seychelles, "248" }, + { QLocale::SierraLeone, "232" }, + { QLocale::Singapore, "65" }, + { QLocale::Slovakia, "421" }, + { QLocale::Slovenia, "386" }, + { QLocale::SolomonIslands, "677" }, + { QLocale::Somalia, "252" }, + { QLocale::SouthAfrica, "27" }, + { QLocale::Spain, "34" }, + { QLocale::SriLanka, "94" }, + { QLocale::Sudan, "249" }, + { QLocale::Suriname, "597" }, + { QLocale::Swaziland, "268" }, + { QLocale::Sweden, "46" }, + { QLocale::Switzerland, "41" }, + { QLocale::Syria, "963" }, + { QLocale::Taiwan, "886" }, + { QLocale::Tajikistan, "992" }, + { QLocale::Tanzania, "255" }, + { QLocale::Thailand, "66" }, + { QLocale::Togo, "228" }, + { QLocale::Tokelau, "690" }, + { QLocale::Tonga, "676" }, + { QLocale::TrinidadAndTobago, "1" }, + { QLocale::Tunisia, "216" }, + { QLocale::Turkey, "90" }, + { QLocale::Turkmenistan, "993" }, + { QLocale::TurksAndCaicosIslands, "1" }, + { QLocale::Tuvalu, "688" }, + { QLocale::Uganda, "256" }, + { QLocale::Ukraine, "380" }, + { QLocale::UnitedArabEmirates, "971" }, + { QLocale::UnitedKingdom, "44" }, + { QLocale::UnitedStates, "1" }, + { QLocale::Uruguay, "598" }, + { QLocale::Uzbekistan, "998" }, + { QLocale::Vanuatu, "678" }, + { QLocale::Venezuela, "58" }, + { QLocale::Vietnam, "84" }, + { QLocale::WallisAndFutunaIslands, "681" }, + { QLocale::Yemen, "967" }, + { QLocale::Zambia, "260" }, + { QLocale::Zimbabwe, "263" } }; // ----------------------------------------------------------------------------- @@ -256,41 +256,38 @@ const QList> TelephoneNumbersModel::mCountryCod TelephoneNumbersModel::TelephoneNumbersModel (QObject *parent) : QAbstractListModel(parent) {} int TelephoneNumbersModel::rowCount (const QModelIndex &) const { - return mCountryCodes.count(); + return mCountryCodes.count(); } QHash TelephoneNumbersModel::roleNames () const { - QHash roles; - roles[Qt::DisplayRole] = "$phoneNumber"; - return roles; + QHash roles; + roles[Qt::DisplayRole] = "countryCode"; + roles[Qt::DisplayRole+1] = "countryName"; + return roles; } QVariant TelephoneNumbersModel::data (const QModelIndex &index, int role) const { - int row = index.row(); - - if (!index.isValid() || row < 0 || row >= mCountryCodes.count()) - return QVariant(); - - if (role == Qt::DisplayRole) { - const QPair &countryCode = mCountryCodes[row]; - - QVariantMap map; - map["countryCode"] = countryCode.second; - map["countryName"] = QStringLiteral("%1 (+%2)") - .arg(Utils::getCountryName(countryCode.first)) - .arg(countryCode.second); - return map; - } - - return QVariant(); + int row = index.row(); + + if (!index.isValid() || row < 0 || row >= mCountryCodes.count()) + return QVariant(); + const QPair &countryCode = mCountryCodes[row]; + if (role == Qt::DisplayRole) { + return countryCode.second; + }else if(role == Qt::DisplayRole+1) + return QStringLiteral("%1 (+%2)") + .arg(Utils::getCountryName(countryCode.first)) + .arg(countryCode.second); + + return QVariant(); } int TelephoneNumbersModel::getDefaultIndex () const { - QLocale::Country country = QLocale().country(); - const auto it = find_if( - mCountryCodes.cbegin(), mCountryCodes.cend(), [&country](const QPair &pair) { - return country == pair.first; - } - ); - return it != mCountryCodes.cend() ? int(distance(mCountryCodes.cbegin(), it)) : 0; + QLocale::Country country = QLocale().country(); + const auto it = find_if( + mCountryCodes.cbegin(), mCountryCodes.cend(), [&country](const QPair &pair) { + return country == pair.first; + } + ); + return it != mCountryCodes.cend() ? int(distance(mCountryCodes.cbegin(), it)) : 0; } diff --git a/linphone-app/src/utils/Utils.cpp b/linphone-app/src/utils/Utils.cpp index 0294d1b06..f9527a218 100644 --- a/linphone-app/src/utils/Utils.cpp +++ b/linphone-app/src/utils/Utils.cpp @@ -31,6 +31,7 @@ #include "components/contacts/ContactsListModel.hpp" #include "components/contact/ContactModel.hpp" #include "components/contact/VcardModel.hpp" +#include "components/settings/AccountSettingsModel.hpp" #include "components/settings/SettingsModel.hpp" #include "app/paths/Paths.hpp" @@ -517,4 +518,12 @@ QString Utils::computeUserAgent(const std::shared_ptr& config) .arg(SettingsModel::getDeviceName(config)) .arg(QSysInfo::prettyProductName()) .arg(qVersion()); -} \ No newline at end of file +} + +bool Utils::isMe(const QString& address){ + return !address.isEmpty() ? CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress()->weakEqual(Utils::interpretUrl(address)) : false; +} + +bool Utils::isMe(const std::shared_ptr& address){ + return address ? CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress()->weakEqual(address) : false; +} diff --git a/linphone-app/src/utils/Utils.hpp b/linphone-app/src/utils/Utils.hpp index db10a6179..4bb7ceb16 100644 --- a/linphone-app/src/utils/Utils.hpp +++ b/linphone-app/src/utils/Utils.hpp @@ -59,6 +59,7 @@ public: Q_INVOKABLE static QString toDateString(QDateTime date); Q_INVOKABLE static QString getDisplayName(const QString& address); Q_INVOKABLE static QString toString(const LinphoneEnums::TunnelMode& mode); + Q_INVOKABLE static bool isMe(const QString& address); //---------------------------------------------------------------------------------- static inline QString coreStringToAppString (const std::string &str) { @@ -128,6 +129,9 @@ public: static QString getDisplayName(const std::shared_ptr& address); // Get the displayname from addres in this order : Friends, Contact, Display address, Username address static std::shared_ptr getConfigIfExists (const QString& configPath); static QString computeUserAgent(const std::shared_ptr& config); + + static bool isMe(const std::shared_ptr& address); + }; #endif // UTILS_H_ diff --git a/linphone-app/ui/modules/Common/Form/ComboBox.qml b/linphone-app/ui/modules/Common/Form/ComboBox.qml index 18bc30dbb..3ded528a7 100644 --- a/linphone-app/ui/modules/Common/Form/ComboBox.qml +++ b/linphone-app/ui/modules/Common/Form/ComboBox.qml @@ -10,88 +10,126 @@ import 'ComboBox.js' as Logic // ============================================================================= Controls.ComboBox { - id: comboBox - - // --------------------------------------------------------------------------- - - property var iconRole - property bool haveBorder: true - property bool haveMargin: true - property color backgroundColor: ComboBoxStyle.background.color.normal - - // --------------------------------------------------------------------------- - - background: Rectangle { - border { - color: ComboBoxStyle.background.border.color - width: comboBox.haveBorder ? ComboBoxStyle.background.border.width : 0 - } - - color: comboBox.enabled - ? comboBox.backgroundColor - : ComboBoxStyle.background.color.readOnly - - radius: ComboBoxStyle.background.radius - - implicitHeight: ComboBoxStyle.background.height - implicitWidth: ComboBoxStyle.background.width - } - - // --------------------------------------------------------------------------- - - contentItem: Item { - height: comboBox.height - width: comboBox.width - - RowLayout { - anchors { - fill: parent - leftMargin: comboBox.haveMargin ? ComboBoxStyle.contentItem.leftMargin : 0 - } - - spacing: ComboBoxStyle.contentItem.spacing - - Icon { - icon: Logic.getSelectedEntryIcon() - iconSize: ComboBoxStyle.contentItem.iconSize - - visible: icon.length > 0 - } - - Text { - Layout.fillWidth: true - - color: ComboBoxStyle.contentItem.text.color - elide: Text.ElideRight - - font.pointSize: ComboBoxStyle.contentItem.text.pointSize - rightPadding: comboBox.indicator.width + comboBox.spacing - - text: Logic.getSelectedEntryText() - } - } - } - - // --------------------------------------------------------------------------- - - indicator: Icon { - icon: ComboBoxStyle.indicator.dropDown.icon - iconSize: ComboBoxStyle.indicator.dropDown.iconSize - overwriteColor: ComboBoxStyle.indicator.dropDown.color - - x: comboBox.width - width - comboBox.rightPadding - y: comboBox.topPadding + (comboBox.availableHeight - height) / 2 - } - - // --------------------------------------------------------------------------- - - delegate: CommonItemDelegate { - id: item - - container: comboBox - flattenedModel: comboBox.textRole.length && - (typeof modelData !== 'undefined' ? modelData : model) - itemIcon: Logic.getItemIcon(item) - width: comboBox.width - } + id: comboBox + + // --------------------------------------------------------------------------- + + property var iconRole + property bool haveBorder: true + property bool haveMargin: true + property color backgroundColor: ComboBoxStyle.background.color.normal + property color foregroundColor: ComboBoxStyle.contentItem.text.color + + property var rootItem + property int yPopup: rootItem ? -mapToItem(rootItem,x,y).y : height + 1 + property int maxPopupHeight : rootItem ? rootItem.height : 400 + + property int selectionWidth: width + + clip: true + // --------------------------------------------------------------------------- + + background: Rectangle { + border { + color: ComboBoxStyle.background.border.color + width: comboBox.haveBorder ? ComboBoxStyle.background.border.width : 0 + } + + color: comboBox.enabled + ? comboBox.backgroundColor + : ComboBoxStyle.background.color.readOnly + + radius: ComboBoxStyle.background.radius + + implicitHeight: ComboBoxStyle.background.height + implicitWidth: ComboBoxStyle.background.width + } + + // --------------------------------------------------------------------------- + + contentItem: Item { + height: comboBox.height + width: comboBox.selectionWidth + clip: true + RowLayout { + anchors { + fill: parent + leftMargin: comboBox.haveMargin ? ComboBoxStyle.contentItem.leftMargin : 0 + } + + spacing: ComboBoxStyle.contentItem.spacing + + Icon { + icon: Logic.getSelectedEntryIcon() + iconSize: ComboBoxStyle.contentItem.iconSize + + visible: icon.length > 0 + } + + Text { + Layout.fillWidth: true + + color: comboBox.foregroundColor + elide: Text.ElideRight + + font.pointSize: ComboBoxStyle.contentItem.text.pointSize + rightPadding: comboBox.indicator.width + comboBox.spacing + + text: Logic.getSelectedEntryText() + } + } + } + + // --------------------------------------------------------------------------- + + indicator: Icon { + icon: ComboBoxStyle.indicator.dropDown.icon + iconSize: ComboBoxStyle.indicator.dropDown.iconSize + overwriteColor: ComboBoxStyle.indicator.dropDown.color + + x: comboBox.width - width - comboBox.rightPadding + y: comboBox.topPadding + (comboBox.availableHeight - height) / 2 + } + + // --------------------------------------------------------------------------- + /* + delegate: CommonItemDelegate { + id: item + clip: true + container: comboBox + flattenedModel: comboBox.textRole.length && + (typeof modelData !== 'undefined' ? modelData : model) + itemIcon: Logic.getItemIcon(item) + width: comboBox.selectionWidth + onWidthChanged: console.log(width) + }*/ + popup: Controls.Popup{ + y: comboBox.yPopup + width: comboBox.selectionWidth + //height: comboBox.maxPopupHeight + //height: contentItem.contentHeight + implicitHeight: contentItem.contentHeight + topPadding: 0 + bottomPadding: 0 + leftPadding: 0 + rightPadding: 0 + contentItem: ListItemSelector{ + //implicitHeight: contentHeight + model: comboBox.popup.visible ? comboBox.model : null + currentIndex: comboBox.highlightedIndex + textRole: comboBox.textRole + onActivated: {comboBox.activated(index);comboBox.currentIndex = index;comboBox.popup.close()} + /* + delegate: CommonItemDelegate { + id: item + clip: true + container: comboBox + flattenedModel: comboBox.textRole.length && + (typeof modelData !== 'undefined' ? modelData : model) + itemIcon: Logic.getItemIcon(item) + width: comboBox.selectionWidth + onWidthChanged: console.log(width) + }*/ + } + } } diff --git a/linphone-app/ui/modules/Common/Form/CommonItemDelegate.qml b/linphone-app/ui/modules/Common/Form/CommonItemDelegate.qml index 176200096..b18e6c3cf 100644 --- a/linphone-app/ui/modules/Common/Form/CommonItemDelegate.qml +++ b/linphone-app/ui/modules/Common/Form/CommonItemDelegate.qml @@ -8,72 +8,70 @@ import Common.Styles 1.0 // ============================================================================= Controls.ItemDelegate { - id: item - - property var container - property var flattenedModel - property var itemIcon - - default property alias _content: content.data - - hoverEnabled: true - - background: Rectangle { - color: item.hovered - ? CommonItemDelegateStyle.color.hovered - : CommonItemDelegateStyle.color.normal - - Rectangle { - anchors.left: parent.left - color: CommonItemDelegateStyle.indicator.color - - height: parent.height - width: CommonItemDelegateStyle.indicator.width - - visible: item.hovered - } - - Rectangle { - anchors.bottom: parent.bottom - color: CommonItemDelegateStyle.separator.color - - height: CommonItemDelegateStyle.separator.height - width: parent.width - - visible: container.count !== index + 1 - } - } - - contentItem: RowLayout { - spacing: CommonItemDelegateStyle.contentItem.spacing - width: item.width - - Icon { - icon: item.itemIcon - iconSize: CommonItemDelegateStyle.contentItem.iconSize - - visible: icon.length > 0 - } - - Text { - Layout.fillWidth: true - - color: CommonItemDelegateStyle.contentItem.text.color - elide: Text.ElideRight - - font { - bold: container.currentIndex === index - pointSize: CommonItemDelegateStyle.contentItem.text.pointSize - } - - text: item.flattenedModel[container.textRole] || modelData - } - - Item { - id: content - - Layout.preferredWidth: CommonItemDelegateStyle.contentItem.iconSize - Layout.preferredHeight: CommonItemDelegateStyle.contentItem.iconSize - } - } + id: item + + property var container + property var flattenedModel + property var itemIcon + + default property alias _content: content.data + + hoverEnabled: true + background: Rectangle { + color: item.hovered + ? CommonItemDelegateStyle.color.hovered + : CommonItemDelegateStyle.color.normal + Rectangle { + anchors.left: parent.left + color: CommonItemDelegateStyle.indicator.color + + height: parent.height + width: CommonItemDelegateStyle.indicator.width + + visible: item.hovered + } + + Rectangle { + anchors.bottom: parent.bottom + color: CommonItemDelegateStyle.separator.color + + height: CommonItemDelegateStyle.separator.height + width: parent.width + + visible: container.count !== index + 1 + } + } + + contentItem: RowLayout { + spacing: CommonItemDelegateStyle.contentItem.spacing + width: item.width + + Icon { + icon: item.itemIcon + iconSize: CommonItemDelegateStyle.contentItem.iconSize + + visible: icon.length > 0 + } + + Text { + Layout.fillWidth: true + + color: CommonItemDelegateStyle.contentItem.text.color + elide: Text.ElideRight + + font { + bold: container.currentIndex === index + pointSize: CommonItemDelegateStyle.contentItem.text.pointSize + } + + text: item.flattenedModel[container.textRole] || modelData + } + + Item { + id: content + + Layout.preferredWidth: CommonItemDelegateStyle.contentItem.iconSize + Layout.preferredHeight: CommonItemDelegateStyle.contentItem.iconSize + } + } } diff --git a/linphone-app/ui/modules/Common/Form/Fields/ScrollableListViewField.qml b/linphone-app/ui/modules/Common/Form/Fields/ScrollableListViewField.qml index d877183ff..edf835a2d 100644 --- a/linphone-app/ui/modules/Common/Form/Fields/ScrollableListViewField.qml +++ b/linphone-app/ui/modules/Common/Form/Fields/ScrollableListViewField.qml @@ -14,8 +14,8 @@ Rectangle { property QtObject textFieldStyle : TextFieldStyle.normal - color: textFieldStyle.background.color.normal - radius: textFieldStyle.background.radius + color: textFieldStyle ? textFieldStyle.background.color.normal : undefined + radius: textFieldStyle ? textFieldStyle.background.radius : 0 Item { id: content @@ -27,8 +27,8 @@ Rectangle { anchors.fill: parent border { - color: textFieldStyle.background.border.color.normal - width: textFieldStyle.background.border.width + color: textFieldStyle ? textFieldStyle.background.border.color.normal : undefined + width: textFieldStyle ? textFieldStyle.background.border.width : 0 } color: 'transparent' @@ -37,7 +37,7 @@ Rectangle { Rectangle { anchors.fill: parent - color: textFieldStyle.background.color.readOnly + color: textFieldStyle ? textFieldStyle.background.color.readOnly : undefined opacity: 0.8 visible: field.readOnly } diff --git a/linphone-app/ui/modules/Common/Form/ListItemSelector.qml b/linphone-app/ui/modules/Common/Form/ListItemSelector.qml index 228540f99..f65c0d137 100644 --- a/linphone-app/ui/modules/Common/Form/ListItemSelector.qml +++ b/linphone-app/ui/modules/Common/Form/ListItemSelector.qml @@ -1,3 +1,6 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.2 + import Common 1.0 import 'ListItemSelector.js' as Logic @@ -5,38 +8,39 @@ import 'ListItemSelector.js' as Logic // ============================================================================= ScrollableListViewField { - property alias currentIndex: view.currentIndex - property alias iconRole: view.iconRole - property alias model: view.model - property alias textRole: view.textRole - - signal activated (int index) - - radius: 0 - - ScrollableListView { - id: view - - // ------------------------------------------------------------------------- - - property string textRole - property var iconRole - - // ------------------------------------------------------------------------- - - anchors.fill: parent - currentIndex: -1 - - delegate: CommonItemDelegate { - id: item - - container: view - flattenedModel: view.textRole.length && - (typeof modelData !== 'undefined' ? modelData : model) - itemIcon: Logic.getItemIcon(item) - width: parent.width - - onClicked: activated(index) - } - } + property alias currentIndex: view.currentIndex + property alias iconRole: view.iconRole + property alias model: view.model + property alias textRole: view.textRole + property alias contentHeight: view.contentHeight + //property alias implicitHeight: view.implicitHeight + //implicitHeight: view.implicitHeight + + signal activated (int index) + color: 'red' + radius: 0 + ScrollableListView { + id: view + + // ------------------------------------------------------------------------- + + property string textRole + property var iconRole + onContentHeightChanged: parent.implicitHeight = contentHeight + + // ------------------------------------------------------------------------- + + anchors.fill: parent + currentIndex: -1 + delegate: CommonItemDelegate { + id: item + + container: view + flattenedModel: view.textRole.length && + (typeof modelData !== 'undefined' ? modelData : model) + itemIcon: Logic.getItemIcon(item) + width: view.width + onClicked: {activated(index)} + } + } } diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatDeliveries.qml b/linphone-app/ui/modules/Linphone/Chat/ChatDeliveries.qml index 1e2b7d645..9758001ae 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatDeliveries.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatDeliveries.qml @@ -47,11 +47,11 @@ Loader{ //: 'Read by %1 - %2' Little message to indicate the state of a message //~ Context %1 is someone, %2 is a date/time. The state that the message has been read. return qsTr('deliveryDisplayed').arg(displayName).arg(stateChangeTime) - else if(state == LinphoneEnums.ChatMessageStateNotDelivered) + else// if(state == LinphoneEnums.ChatMessageStateNotDelivered) //: "%1 have nothing received" Little message to indicate the state of a message //~ Context %1 is someone. The state is that the message hasn't been delivered. return qsTr('deliveryNotDelivered').arg(displayName) - else return '' + //else return '' } delegate:Text{ height: ChatStyle.composingText.height-5 diff --git a/linphone-app/ui/modules/Linphone/Menus/SipAddressesMenu.qml b/linphone-app/ui/modules/Linphone/Menus/SipAddressesMenu.qml index 9188bf3be..4acbd6138 100644 --- a/linphone-app/ui/modules/Linphone/Menus/SipAddressesMenu.qml +++ b/linphone-app/ui/modules/Linphone/Menus/SipAddressesMenu.qml @@ -75,7 +75,7 @@ Item { delegate: Rectangle { height: menu.entryHeight - width: parent.width + width: list.width color: mouseArea.pressed ? SipAddressesMenuStyle.entry.color.pressed diff --git a/linphone-app/ui/views/App/Dialog/NewConference.qml b/linphone-app/ui/views/App/Dialog/NewConference.qml index 855113974..5ba0ccbbc 100644 --- a/linphone-app/ui/views/App/Dialog/NewConference.qml +++ b/linphone-app/ui/views/App/Dialog/NewConference.qml @@ -17,10 +17,11 @@ import 'qrc:/ui/scripts/Utils/utils.js' as Utils DialogPlus { id: conferenceManager - property ConferenceInfoModel conferenceInfoModel: ConferenceInfoModel{ - property bool isNew: true - } - onConferenceInfoModelChanged: if( conferenceInfoModel && !conferenceInfoModel.isNew) selectedParticipants.setAddresses(conferenceInfoModel) + property bool isNew: !conferenceInfoModel || conferenceInfoModel.uri === '' + onIsNewChanged: console.log("Is New:"+isNew+", "+conferenceInfoModel + ", " + (conferenceInfoModel? conferenceInfoModel.uri : 'noUri')) + Component.onCompleted: console.log("Completed: Is New:"+isNew+", "+conferenceInfoModel + ", " + (conferenceInfoModel? conferenceInfoModel.uri : 'noUri')) + property ConferenceInfoModel conferenceInfoModel: ConferenceInfoModel{} + onConferenceInfoModelChanged: selectedParticipants.setAddresses(conferenceInfoModel) Connections{ target: conferenceInfoModel onConferenceCreated: { @@ -107,7 +108,7 @@ DialogPlus { TextButtonB { enabled: selectedParticipants.count >= conferenceManager.minParticipants && subject.text != '' && AccountSettingsModel.conferenceURI != '' //: 'Launch' : Start button - text: conferenceInfoModel.isNew ? qsTr('startButton') : 'Mettre à jour' + text: conferenceManager.isNew ? qsTr('startButton') : 'Mettre à jour' capitalization: Font.AllUppercase function getInviteMode(){ @@ -166,7 +167,7 @@ DialogPlus { buttonsAlignment: Qt.AlignRight buttonsLeftMargin: 15 //: 'Start a video conference' : Title of a popup about creation of a video conference - title: conferenceInfoModel.isNew ? qsTr('newConferenceTitle') : 'Changer la conférence' + title: conferenceManager.isNew ? qsTr('newConferenceTitle') : 'Changer la conférence' height: window.height - 100 width: window.width - 100 @@ -227,7 +228,7 @@ DialogPlus { Layout.alignment: Qt.AlignVCenter width:50 enabled: true - checked: true + checked: conferenceInfoModel.isScheduled onClicked: { checked = !checked @@ -254,7 +255,7 @@ DialogPlus { property var locale: Qt.locale() property date currentDate: new Date() property int cellWidth: (parent.width-15)/columns - Component.onCompleted: scheduleForm.updateDateTime() + //Component.onCompleted: scheduleForm.updateDateTime() @@ -270,6 +271,7 @@ DialogPlus { function setDate(date){ text = date.toLocaleDateString(scheduleForm.locale, 'yyyy/MM/dd') } + text: conferenceManager.conferenceInfoModel? conferenceManager.conferenceInfoModel.dateTime.toLocaleDateString(scheduleForm.locale, 'yyyy/MM/dd') : '' MouseArea{ anchors.fill: parent onClicked: { @@ -293,6 +295,7 @@ DialogPlus { function setTime(date){ text = date.toLocaleTimeString(scheduleForm.locale, 'hh:mm') } + text: conferenceManager.conferenceInfoModel? conferenceManager.conferenceInfoModel.dateTime.toLocaleTimeString(scheduleForm.locale, 'hh:mm') : '' MouseArea{ anchors.top: parent.top anchors.bottom: parent.bottom @@ -311,8 +314,21 @@ DialogPlus { } } } - NumericField{id: durationField; text: '1200'; Layout.preferredWidth: parent.cellWidth; color: NewConferenceStyle.fields.textColor; font.weight: NewConferenceStyle.fields.weight; font.pointSize: NewConferenceStyle.fields.pointSize} - TextField{ text: 'Paris'; readOnly: true; Layout.preferredWidth: parent.cellWidth; color: NewConferenceStyle.fields.textColor; font.weight: NewConferenceStyle.fields.weight; font.pointSize: NewConferenceStyle.fields.pointSize} + NumericField{id: durationField; Layout.preferredWidth: parent.cellWidth; color: NewConferenceStyle.fields.textColor; font.weight: NewConferenceStyle.fields.weight; font.pointSize: NewConferenceStyle.fields.pointSize + text: conferenceManager.conferenceInfoModel ? conferenceManager.conferenceInfoModel.duration : '1200' + } + ComboBox{ + Layout.preferredWidth: parent.cellWidth; + //color: NewConferenceStyle.fields.textColor; font.weight: NewConferenceStyle.fields.weight; font.pointSize: NewConferenceStyle.fields.pointSize + currentIndex: model.defaultIndex + model: TimeZoneProxyModel{} + onActivated: console.log("activated : " +index) + textRole: "displayText" + selectionWidth: 500 + rootItem: conferenceManager + } + //TextField{ text: 'Paris'; readOnly: true; Layout.preferredWidth: parent.cellWidth; color: NewConferenceStyle.fields.textColor; font.weight: NewConferenceStyle.fields.weight; font.pointSize: NewConferenceStyle.fields.pointSize} + function updateDateTime(){ var storedDate if( dateField.text != '' && timeField.text != ''){ @@ -327,11 +343,13 @@ DialogPlus { } } Timer{ - running: scheduleForm.visible + running: scheduleForm.visible && conferenceManager.isNew repeat: true interval: 1000 + triggeredOnStart: true onTriggered: { - scheduleForm.updateDateTime() + if(conferenceManager.isNew) + scheduleForm.updateDateTime() } } } @@ -358,7 +376,7 @@ DialogPlus { Layout.fillHeight: true //: 'Description' : Placeholder in a form about setting a description placeholderText : 'Description' - text: '' + text: conferenceManager.conferenceInfoModel ? conferenceManager.conferenceInfoModel.description : '' Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus() TooltipArea{ //: 'This description will describe the conference' : Explanation about the description of the conference @@ -484,7 +502,7 @@ DialogPlus { anchors.fill: parent showContactAddress:false - showSwitch : conferenceInfoModel.isNew + showSwitch : conferenceManager.isNew showSeparator: false isSelectable: false showInvitingIndicator: false diff --git a/linphone-app/ui/views/App/Main/Assistant/CreateAppSipAccountWithPhoneNumber.qml b/linphone-app/ui/views/App/Main/Assistant/CreateAppSipAccountWithPhoneNumber.qml index 61cbefc6a..218e37d0a 100644 --- a/linphone-app/ui/views/App/Main/Assistant/CreateAppSipAccountWithPhoneNumber.qml +++ b/linphone-app/ui/views/App/Main/Assistant/CreateAppSipAccountWithPhoneNumber.qml @@ -12,8 +12,10 @@ AssistantAbstractView { property alias phoneNumberError: phoneNumber.error function setCountryCode (index) { - var model = country.model - assistantModel.countryCode = model.data(model.index(index, 0)).countryCode + if(index>=0){ + var model = country.model + assistantModel.countryCode = model.data(model.index(index, 0),"countryCode") + } } title: qsTr('createAppSipAccountTitle').replace('%1', Qt.application.name.toUpperCase()) diff --git a/linphone-sdk b/linphone-sdk index 0bf934b06..e3f284058 160000 --- a/linphone-sdk +++ b/linphone-sdk @@ -1 +1 @@ -Subproject commit 0bf934b0669e77ddecfcd8298ea615bb998aa28a +Subproject commit e3f284058e17f0e01e6005659532a437ea1b0a34