Contacts list refactoring + Update SDK for fixing LDAP timeout.
This commit is contained in:
parent
213ba75585
commit
de2612b40e
16 changed files with 549 additions and 553 deletions
|
|
@ -24,6 +24,7 @@ LimitProxy::LimitProxy(QObject *parent) : QSortFilterProxyModel(parent) {
|
||||||
connect(this, &LimitProxy::rowsInserted, this, &LimitProxy::countChanged);
|
connect(this, &LimitProxy::rowsInserted, this, &LimitProxy::countChanged);
|
||||||
connect(this, &LimitProxy::rowsRemoved, this, &LimitProxy::countChanged);
|
connect(this, &LimitProxy::rowsRemoved, this, &LimitProxy::countChanged);
|
||||||
connect(this, &LimitProxy::modelReset, this, &LimitProxy::countChanged);
|
connect(this, &LimitProxy::modelReset, this, &LimitProxy::countChanged);
|
||||||
|
connect(this, &LimitProxy::countChanged, this, &LimitProxy::haveMoreChanged);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
LimitProxy::LimitProxy(QAbstractItemModel *sortFilterProxy, QObject *parent) : QSortFilterProxyModel(parent) {
|
LimitProxy::LimitProxy(QAbstractItemModel *sortFilterProxy, QObject *parent) : QSortFilterProxyModel(parent) {
|
||||||
|
|
@ -79,7 +80,7 @@ int LimitProxy::getInitialDisplayItems() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimitProxy::setInitialDisplayItems(int initialItems) {
|
void LimitProxy::setInitialDisplayItems(int initialItems) {
|
||||||
if (initialItems != 0 && mInitialDisplayItems != initialItems) {
|
if (mInitialDisplayItems != initialItems) {
|
||||||
mInitialDisplayItems = initialItems;
|
mInitialDisplayItems = initialItems;
|
||||||
if (getMaxDisplayItems() <= mInitialDisplayItems) setMaxDisplayItems(initialItems);
|
if (getMaxDisplayItems() <= mInitialDisplayItems) setMaxDisplayItems(initialItems);
|
||||||
if (getDisplayItemsStep() <= 0) setDisplayItemsStep(initialItems);
|
if (getDisplayItemsStep() <= 0) setDisplayItemsStep(initialItems);
|
||||||
|
|
@ -99,7 +100,7 @@ int LimitProxy::getMaxDisplayItems() const {
|
||||||
return mMaxDisplayItems;
|
return mMaxDisplayItems;
|
||||||
}
|
}
|
||||||
void LimitProxy::setMaxDisplayItems(int maxItems) {
|
void LimitProxy::setMaxDisplayItems(int maxItems) {
|
||||||
if (maxItems != 0 && mMaxDisplayItems != maxItems) {
|
if (mMaxDisplayItems != maxItems) {
|
||||||
auto model = sourceModel();
|
auto model = sourceModel();
|
||||||
int modelCount = model ? model->rowCount() : 0;
|
int modelCount = model ? model->rowCount() : 0;
|
||||||
int oldCount = getDisplayCount(modelCount);
|
int oldCount = getDisplayCount(modelCount);
|
||||||
|
|
@ -125,6 +126,12 @@ void LimitProxy::setDisplayItemsStep(int step) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LimitProxy::getHaveMore() const {
|
||||||
|
auto model = sourceModel();
|
||||||
|
int modelCount = model ? model->rowCount() : 0;
|
||||||
|
return getCount() < modelCount;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
QString LimitProxy::getFilterText() const {
|
QString LimitProxy::getFilterText() const {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ public:
|
||||||
initialDisplayItemsChanged)
|
initialDisplayItemsChanged)
|
||||||
Q_PROPERTY(int maxDisplayItems READ getMaxDisplayItems WRITE setMaxDisplayItems NOTIFY maxDisplayItemsChanged)
|
Q_PROPERTY(int maxDisplayItems READ getMaxDisplayItems WRITE setMaxDisplayItems NOTIFY maxDisplayItemsChanged)
|
||||||
Q_PROPERTY(int displayItemsStep READ getDisplayItemsStep WRITE setDisplayItemsStep NOTIFY displayItemsStepChanged)
|
Q_PROPERTY(int displayItemsStep READ getDisplayItemsStep WRITE setDisplayItemsStep NOTIFY displayItemsStepChanged)
|
||||||
|
Q_PROPERTY(bool haveMore READ getHaveMore NOTIFY haveMoreChanged)
|
||||||
|
|
||||||
// Propagation
|
// Propagation
|
||||||
Q_PROPERTY(QString filterText READ getFilterText WRITE setFilterText NOTIFY filterTextChanged)
|
Q_PROPERTY(QString filterText READ getFilterText WRITE setFilterText NOTIFY filterTextChanged)
|
||||||
|
|
@ -72,6 +73,8 @@ public:
|
||||||
int getDisplayItemsStep() const;
|
int getDisplayItemsStep() const;
|
||||||
void setDisplayItemsStep(int step);
|
void setDisplayItemsStep(int step);
|
||||||
|
|
||||||
|
bool getHaveMore() const;
|
||||||
|
|
||||||
//-------------------------------------------------------------
|
//-------------------------------------------------------------
|
||||||
QString getFilterText() const;
|
QString getFilterText() const;
|
||||||
void setFilterText(const QString &filter);
|
void setFilterText(const QString &filter);
|
||||||
|
|
@ -92,6 +95,7 @@ signals:
|
||||||
void initialDisplayItemsChanged();
|
void initialDisplayItemsChanged();
|
||||||
void maxDisplayItemsChanged();
|
void maxDisplayItemsChanged();
|
||||||
void displayItemsStepChanged();
|
void displayItemsStepChanged();
|
||||||
|
void haveMoreChanged();
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
void filterTypeChanged(int filterType);
|
void filterTypeChanged(int filterType);
|
||||||
void filterTextChanged();
|
void filterTextChanged();
|
||||||
|
|
|
||||||
|
|
@ -71,14 +71,15 @@ public:
|
||||||
Q_INVOKABLE void remove(int index, int count = 1);
|
Q_INVOKABLE void remove(int index, int count = 1);
|
||||||
void invalidateFilter();
|
void invalidateFilter();
|
||||||
|
|
||||||
|
int mFilterType = 0;
|
||||||
|
QString mFilterText;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void countChanged();
|
void countChanged();
|
||||||
void filterTypeChanged(int filterType);
|
void filterTypeChanged(int filterType);
|
||||||
void filterTextChanged();
|
void filterTextChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int mFilterType = 0;
|
|
||||||
QString mFilterText;
|
|
||||||
bool mDeleteSourceModel = false;
|
bool mDeleteSourceModel = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -224,3 +224,17 @@ int MagicSearchList::findFriendIndexByAddress(const QString &address) {
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSharedPointer<FriendCore> MagicSearchList::findFriendByAddress(const QString &address) {
|
||||||
|
for (int i = 0; i < getCount(); ++i) {
|
||||||
|
auto friendCore = getAt<FriendCore>(i);
|
||||||
|
if (!friendCore) continue;
|
||||||
|
for (auto &friendAddress : friendCore->getAllAddresses()) {
|
||||||
|
auto map = friendAddress.toMap();
|
||||||
|
if (map["address"].toString() == address) {
|
||||||
|
return friendCore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ public:
|
||||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
int findFriendIndexByAddress(const QString &address);
|
int findFriendIndexByAddress(const QString &address);
|
||||||
|
QSharedPointer<FriendCore> findFriendByAddress(const QString &address);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -68,9 +68,7 @@ void MagicSearchProxy::setList(QSharedPointer<MagicSearchList> newList) {
|
||||||
}
|
}
|
||||||
auto sortFilterList = new SortFilterList(mList.get(), Qt::AscendingOrder);
|
auto sortFilterList = new SortFilterList(mList.get(), Qt::AscendingOrder);
|
||||||
if (oldModel) {
|
if (oldModel) {
|
||||||
sortFilterList->mShowFavoritesOnly = oldModel->mShowFavoritesOnly;
|
sortFilterList->mFilterType = oldModel->mFilterType;
|
||||||
sortFilterList->mHideSuggestions = oldModel->mHideSuggestions;
|
|
||||||
sortFilterList->mShowLdapContacts = oldModel->mShowLdapContacts;
|
|
||||||
sortFilterList->mHideListProxy = oldModel->mHideListProxy;
|
sortFilterList->mHideListProxy = oldModel->mHideListProxy;
|
||||||
if (sortFilterList->mHideListProxy) {
|
if (sortFilterList->mHideListProxy) {
|
||||||
connect(sortFilterList->mHideListProxy, &MagicSearchProxy::countChanged, sortFilterList,
|
connect(sortFilterList->mHideListProxy, &MagicSearchProxy::countChanged, sortFilterList,
|
||||||
|
|
@ -82,7 +80,7 @@ void MagicSearchProxy::setList(QSharedPointer<MagicSearchList> newList) {
|
||||||
connect(
|
connect(
|
||||||
mList.get(), &MagicSearchList::friendStarredChanged, this,
|
mList.get(), &MagicSearchList::friendStarredChanged, this,
|
||||||
[this, sortFilterList]() {
|
[this, sortFilterList]() {
|
||||||
if (showFavoritesOnly()) sortFilterList->invalidate();
|
if ((getFilterType() & (int)FilteringTypes::Favorites) > 0) sortFilterList->invalidate();
|
||||||
},
|
},
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
setSourceModels(sortFilterList);
|
setSourceModels(sortFilterList);
|
||||||
|
|
@ -98,6 +96,27 @@ int MagicSearchProxy::findFriendIndexByAddress(const QString &address) {
|
||||||
} else return -1;
|
} else return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FriendGui *MagicSearchProxy::findFriendByAddress(const QString &address) {
|
||||||
|
auto magicSearchList = getListModel<MagicSearchList>();
|
||||||
|
if (magicSearchList) {
|
||||||
|
auto friendCore = magicSearchList->findFriendByAddress(address);
|
||||||
|
return friendCore ? new FriendGui(friendCore) : nullptr;
|
||||||
|
} else return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MagicSearchProxy::loadUntil(const QString &address) {
|
||||||
|
auto magicSearchList = getListModel<MagicSearchList>();
|
||||||
|
if (magicSearchList) {
|
||||||
|
auto listIndex = magicSearchList->findFriendIndexByAddress(address);
|
||||||
|
if (listIndex == -1) return -1;
|
||||||
|
listIndex =
|
||||||
|
dynamic_cast<SortFilterList *>(sourceModel())->mapFromSource(magicSearchList->index(listIndex, 0)).row();
|
||||||
|
if (mMaxDisplayItems < listIndex) setMaxDisplayItems(listIndex + 1);
|
||||||
|
return listIndex;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
QString MagicSearchProxy::getSearchText() const {
|
QString MagicSearchProxy::getSearchText() const {
|
||||||
return mSearchText;
|
return mSearchText;
|
||||||
}
|
}
|
||||||
|
|
@ -125,31 +144,6 @@ void MagicSearchProxy::setMaxResults(int flags) {
|
||||||
mList->setMaxResults(flags);
|
mList->setMaxResults(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MagicSearchProxy::showFavoritesOnly() const {
|
|
||||||
return dynamic_cast<SortFilterList *>(sourceModel())->mShowFavoritesOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MagicSearchProxy::setShowFavoritesOnly(bool show) {
|
|
||||||
auto list = dynamic_cast<SortFilterList *>(sourceModel());
|
|
||||||
if (list->mShowFavoritesOnly != show) {
|
|
||||||
list->mShowFavoritesOnly = show;
|
|
||||||
list->invalidate();
|
|
||||||
emit showFavoriteOnlyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MagicSearchProxy::getHideSuggestions() const {
|
|
||||||
return dynamic_cast<SortFilterList *>(sourceModel())->mHideSuggestions;
|
|
||||||
}
|
|
||||||
void MagicSearchProxy::setHideSuggestions(bool data) {
|
|
||||||
auto list = dynamic_cast<SortFilterList *>(sourceModel());
|
|
||||||
if (list->mHideSuggestions != data) {
|
|
||||||
list->mHideSuggestions = data;
|
|
||||||
list->invalidate();
|
|
||||||
emit hideSuggestionsChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MagicSearchProxy *MagicSearchProxy::getParentProxy() const {
|
MagicSearchProxy *MagicSearchProxy::getParentProxy() const {
|
||||||
return mParentProxy;
|
return mParentProxy;
|
||||||
}
|
}
|
||||||
|
|
@ -193,9 +187,23 @@ bool MagicSearchProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QMo
|
||||||
auto friendCore = getItemAtSource<MagicSearchList, FriendCore>(sourceRow);
|
auto friendCore = getItemAtSource<MagicSearchList, FriendCore>(sourceRow);
|
||||||
auto toShow = false;
|
auto toShow = false;
|
||||||
if (friendCore) {
|
if (friendCore) {
|
||||||
toShow = (!mHideSuggestions || friendCore->getIsStored() || friendCore->isLdap()) &&
|
if (mFilterType == (int)FilteringTypes::None) return false;
|
||||||
(!mShowFavoritesOnly || friendCore->getStarred()) &&
|
if ((mFilterType & (int)FilteringTypes::Favorites) > 0) {
|
||||||
(mShowLdapContacts || (!friendCore->isLdap() || friendCore->getIsStored()));
|
toShow = friendCore->getStarred();
|
||||||
|
if (!toShow) return false;
|
||||||
|
}
|
||||||
|
if ((mFilterType & (int)FilteringTypes::Ldap) > 0) {
|
||||||
|
toShow = friendCore->isLdap();
|
||||||
|
// if (!toShow) return false;
|
||||||
|
}
|
||||||
|
if (!toShow && (mFilterType & (int)FilteringTypes::App) > 0) {
|
||||||
|
toShow = friendCore->getIsStored();
|
||||||
|
// if (!toShow) return false;
|
||||||
|
}
|
||||||
|
if (!toShow && (mFilterType & (int)FilteringTypes::Other) > 0) {
|
||||||
|
toShow = !friendCore->getIsStored() && !friendCore->isLdap();
|
||||||
|
}
|
||||||
|
|
||||||
if (toShow && mHideListProxy) {
|
if (toShow && mHideListProxy) {
|
||||||
for (auto &friendAddress : friendCore->getAllAddresses()) {
|
for (auto &friendAddress : friendCore->getAllAddresses()) {
|
||||||
toShow = mHideListProxy->findFriendIndexByAddress(friendAddress.toMap()["address"].toString()) == -1;
|
toShow = mHideListProxy->findFriendIndexByAddress(friendAddress.toMap()["address"].toString()) == -1;
|
||||||
|
|
@ -222,15 +230,3 @@ bool MagicSearchProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft, c
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MagicSearchProxy::showLdapContacts() const {
|
|
||||||
return dynamic_cast<SortFilterList *>(sourceModel())->mShowLdapContacts;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MagicSearchProxy::setShowLdapContacts(bool show) {
|
|
||||||
auto list = dynamic_cast<SortFilterList *>(sourceModel());
|
|
||||||
if (list->mShowLdapContacts != show) {
|
|
||||||
list->mShowLdapContacts = show;
|
|
||||||
list->invalidateFilter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@
|
||||||
#define MAGIC_SEARCH_PROXY_H_
|
#define MAGIC_SEARCH_PROXY_H_
|
||||||
|
|
||||||
#include "../proxy/LimitProxy.hpp"
|
#include "../proxy/LimitProxy.hpp"
|
||||||
#include "core/friend/FriendGui.hpp"
|
|
||||||
#include "core/search/MagicSearchList.hpp"
|
#include "core/search/MagicSearchList.hpp"
|
||||||
#include "tool/LinphoneEnums.hpp"
|
#include "tool/LinphoneEnums.hpp"
|
||||||
|
|
||||||
|
|
@ -30,24 +29,22 @@
|
||||||
|
|
||||||
class MagicSearchProxy : public LimitProxy {
|
class MagicSearchProxy : public LimitProxy {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") // Avoid name clashes
|
||||||
Q_PROPERTY(QString searchText READ getSearchText WRITE setSearchText NOTIFY searchTextChanged)
|
Q_PROPERTY(QString searchText READ getSearchText WRITE setSearchText NOTIFY searchTextChanged)
|
||||||
Q_PROPERTY(int sourceFlags READ getSourceFlags WRITE setSourceFlags NOTIFY sourceFlagsChanged)
|
Q_PROPERTY(int sourceFlags READ getSourceFlags WRITE setSourceFlags NOTIFY sourceFlagsChanged)
|
||||||
|
|
||||||
Q_PROPERTY(int maxResults READ getMaxResults WRITE setMaxResults NOTIFY maxResultsChanged)
|
Q_PROPERTY(int maxResults READ getMaxResults WRITE setMaxResults NOTIFY maxResultsChanged)
|
||||||
Q_PROPERTY(LinphoneEnums::MagicSearchAggregation aggregationFlag READ getAggregationFlag WRITE setAggregationFlag
|
Q_PROPERTY(LinphoneEnums::MagicSearchAggregation aggregationFlag READ getAggregationFlag WRITE setAggregationFlag
|
||||||
NOTIFY aggregationFlagChanged)
|
NOTIFY aggregationFlagChanged)
|
||||||
Q_PROPERTY(bool showFavoritesOnly READ showFavoritesOnly WRITE setShowFavoritesOnly NOTIFY showFavoriteOnlyChanged)
|
|
||||||
Q_PROPERTY(MagicSearchProxy *parentProxy READ getParentProxy WRITE setParentProxy NOTIFY parentProxyChanged)
|
Q_PROPERTY(MagicSearchProxy *parentProxy READ getParentProxy WRITE setParentProxy NOTIFY parentProxyChanged)
|
||||||
Q_PROPERTY(MagicSearchProxy *hideListProxy READ getHideListProxy WRITE setHideListProxy NOTIFY hideListProxyChanged)
|
Q_PROPERTY(MagicSearchProxy *hideListProxy READ getHideListProxy WRITE setHideListProxy NOTIFY hideListProxyChanged)
|
||||||
|
|
||||||
Q_PROPERTY(bool showLdapContacts READ showLdapContacts WRITE setShowLdapContacts CONSTANT)
|
|
||||||
Q_PROPERTY(bool hideSuggestions READ getHideSuggestions WRITE setHideSuggestions NOTIFY hideSuggestionsChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DECLARE_SORTFILTER_CLASS(bool mShowFavoritesOnly = false; bool mShowLdapContacts = true;
|
enum class FilteringTypes { None = 0, Favorites = 1, App = 2, Ldap = 4, Other = 8 };
|
||||||
bool mHideSuggestions = false;
|
Q_ENUM(FilteringTypes)
|
||||||
MagicSearchProxy *mHideListProxy = nullptr;)
|
|
||||||
|
DECLARE_SORTFILTER_CLASS(MagicSearchProxy *mHideListProxy = nullptr;)
|
||||||
MagicSearchProxy(QObject *parent = Q_NULLPTR);
|
MagicSearchProxy(QObject *parent = Q_NULLPTR);
|
||||||
~MagicSearchProxy();
|
~MagicSearchProxy();
|
||||||
|
|
||||||
|
|
@ -63,15 +60,6 @@ public:
|
||||||
int getMaxResults() const;
|
int getMaxResults() const;
|
||||||
void setMaxResults(int maxResults);
|
void setMaxResults(int maxResults);
|
||||||
|
|
||||||
bool showFavoritesOnly() const;
|
|
||||||
void setShowFavoritesOnly(bool show);
|
|
||||||
|
|
||||||
bool showLdapContacts() const;
|
|
||||||
void setShowLdapContacts(bool show);
|
|
||||||
|
|
||||||
bool getHideSuggestions() const;
|
|
||||||
void setHideSuggestions(bool data);
|
|
||||||
|
|
||||||
MagicSearchProxy *getParentProxy() const;
|
MagicSearchProxy *getParentProxy() const;
|
||||||
void setList(QSharedPointer<MagicSearchList> list);
|
void setList(QSharedPointer<MagicSearchList> list);
|
||||||
Q_INVOKABLE void setParentProxy(MagicSearchProxy *proxy);
|
Q_INVOKABLE void setParentProxy(MagicSearchProxy *proxy);
|
||||||
|
|
@ -81,6 +69,8 @@ public:
|
||||||
|
|
||||||
// Q_INVOKABLE forceUpdate();
|
// Q_INVOKABLE forceUpdate();
|
||||||
Q_INVOKABLE int findFriendIndexByAddress(const QString &address);
|
Q_INVOKABLE int findFriendIndexByAddress(const QString &address);
|
||||||
|
Q_INVOKABLE FriendGui *findFriendByAddress(const QString &address);
|
||||||
|
Q_INVOKABLE int loadUntil(const QString &address);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void searchTextChanged();
|
void searchTextChanged();
|
||||||
|
|
@ -89,8 +79,6 @@ signals:
|
||||||
void maxResultsChanged(int maxResults);
|
void maxResultsChanged(int maxResults);
|
||||||
void forceUpdate();
|
void forceUpdate();
|
||||||
void localFriendCreated(int index);
|
void localFriendCreated(int index);
|
||||||
void showFavoriteOnlyChanged();
|
|
||||||
void hideSuggestionsChanged();
|
|
||||||
void parentProxyChanged();
|
void parentProxyChanged();
|
||||||
void hideListProxyChanged();
|
void hideListProxyChanged();
|
||||||
void initialized();
|
void initialized();
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
||||||
view/Control/Display/Contact/Contact.qml
|
view/Control/Display/Contact/Contact.qml
|
||||||
view/Control/Display/Contact/ContactListItem.qml
|
view/Control/Display/Contact/ContactListItem.qml
|
||||||
view/Control/Display/Contact/ContactListView.qml
|
view/Control/Display/Contact/ContactListView.qml
|
||||||
|
view/Control/Display/Contact/AllContactListView.qml
|
||||||
view/Control/Display/Contact/Voicemail.qml
|
view/Control/Display/Contact/Voicemail.qml
|
||||||
view/Control/Display/Meeting/MeetingListView.qml
|
view/Control/Display/Meeting/MeetingListView.qml
|
||||||
view/Control/Display/Participant/ParticipantDeviceListView.qml
|
view/Control/Display/Participant/ParticipantDeviceListView.qml
|
||||||
|
|
|
||||||
332
Linphone/view/Control/Display/Contact/AllContactListView.qml
Normal file
332
Linphone/view/Control/Display/Contact/AllContactListView.qml
Normal file
|
|
@ -0,0 +1,332 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls.Basic as Control
|
||||||
|
|
||||||
|
import Linphone
|
||||||
|
import UtilsCpp 1.0
|
||||||
|
import ConstantsCpp 1.0
|
||||||
|
import SettingsCpp
|
||||||
|
|
||||||
|
Flickable{
|
||||||
|
id: mainItem
|
||||||
|
|
||||||
|
property bool showInitials: true // Display Initials of Display name.
|
||||||
|
property bool showDefaultAddress: true // Display address below display name.
|
||||||
|
property bool showActions: false // Display actions layout (call buttons)
|
||||||
|
property bool showContactMenu: true // Display the dot menu for contacts.
|
||||||
|
property bool showFavorites: true // Display the favorites in the header
|
||||||
|
property bool hideSuggestions: false // Hide not stored contacts (not suggestions)
|
||||||
|
property string highlightText: searchText // Bold characters in Display name.
|
||||||
|
property var sourceFlags: LinphoneEnums.MagicSearchSource.All
|
||||||
|
|
||||||
|
property bool displayNameCapitalization: true // Capitalize display name.
|
||||||
|
|
||||||
|
property bool selectionEnabled: true // Contact can be selected
|
||||||
|
property bool multiSelectionEnabled: false //Multiple items can be selected.
|
||||||
|
property list<string> selectedContacts // List of default address on selected contacts.
|
||||||
|
//property FriendGui selectedContact//: model.getAt(currentIndex) || null
|
||||||
|
property FriendGui highlightedContact
|
||||||
|
|
||||||
|
property bool searchOnEmpty: true
|
||||||
|
property bool loading: false
|
||||||
|
property bool pauseSearch: false // true = don't search on text change
|
||||||
|
|
||||||
|
// Model properties
|
||||||
|
// set searchBarText without specifying a model to bold
|
||||||
|
// matching names
|
||||||
|
property string searchBarText
|
||||||
|
property string searchText// Binding is done on searchBarTextChanged
|
||||||
|
property ConferenceInfoGui confInfoGui
|
||||||
|
|
||||||
|
property bool haveFavorites: false
|
||||||
|
property bool haveContacts: count > 0
|
||||||
|
property int sectionsPixelSize: 16 * DefaultStyle.dp
|
||||||
|
property int sectionsWeight: 800 * DefaultStyle.dp
|
||||||
|
property int sectionsSpacing: 18 * DefaultStyle.dp
|
||||||
|
|
||||||
|
property int itemsRightMargin: 39 * DefaultStyle.dp
|
||||||
|
property int count: contactsList.count
|
||||||
|
|
||||||
|
signal resultsReceived()
|
||||||
|
signal contactStarredChanged()
|
||||||
|
signal contactDeletionRequested(FriendGui contact)
|
||||||
|
signal contactAddedToSelection(string address)
|
||||||
|
signal contactRemovedFromSelection(string address)
|
||||||
|
signal contactSelected(FriendGui contact)
|
||||||
|
|
||||||
|
contentWidth: width
|
||||||
|
contentHeight: contentsLayout.height
|
||||||
|
|
||||||
|
|
||||||
|
function selectContact(address) {
|
||||||
|
var index = contactsProxy.loadUntil(address)// Be sure to have this address in proxy if it exists
|
||||||
|
if (index != -1) {
|
||||||
|
contactsList.selectIndex(index)
|
||||||
|
}
|
||||||
|
return index
|
||||||
|
|
||||||
|
}
|
||||||
|
function addContactToSelection(address) {
|
||||||
|
if (multiSelectionEnabled) {
|
||||||
|
var indexInSelection = selectedContacts.indexOf(address)
|
||||||
|
if (indexInSelection == -1) {
|
||||||
|
selectedContacts.push(address)
|
||||||
|
contactAddedToSelection(address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function removeContactFromSelection(indexInSelection) {
|
||||||
|
var addressToRemove = selectedContacts[indexInSelection]
|
||||||
|
if (indexInSelection != -1) {
|
||||||
|
selectedContacts.splice(indexInSelection, 1)
|
||||||
|
contactRemovedFromSelection(addressToRemove)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function removeSelectedContactByAddress(address) {
|
||||||
|
var index = selectedContacts.indexOf(address)
|
||||||
|
if (index != -1) {
|
||||||
|
selectedContacts.splice(index, 1)
|
||||||
|
contactRemovedFromSelection(address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function haveAddress(address){
|
||||||
|
var index = magicSearchProxy.findFriendIndexByAddress(address)
|
||||||
|
return index != -1
|
||||||
|
}
|
||||||
|
|
||||||
|
onHighlightedContactChanged:{
|
||||||
|
favoritesList.highlightedContact = highlightedContact
|
||||||
|
contactsList.highlightedContact = highlightedContact
|
||||||
|
suggestionsList.highlightedContact = highlightedContact
|
||||||
|
}
|
||||||
|
|
||||||
|
onResultsReceived: {
|
||||||
|
loading = false
|
||||||
|
mainItem.contentY = 0
|
||||||
|
}
|
||||||
|
onSearchBarTextChanged: {
|
||||||
|
if(!pauseSearch && (mainItem.searchOnEmpty || searchBarText != '')) {
|
||||||
|
searchText = searchBarText.length === 0 ? "*" : searchBarText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onPauseSearchChanged: {
|
||||||
|
if(!pauseSearch && (mainItem.searchOnEmpty || searchBarText != '')){
|
||||||
|
searchText = searchBarText.length === 0 ? "*" : searchBarText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onSearchTextChanged: loading = true
|
||||||
|
onAtYEndChanged: if(atYEnd) {
|
||||||
|
if( contactsProxy.haveMore || mainItem.hideSuggestions) contactsProxy.displayMore()
|
||||||
|
else suggestionsProxy.displayMore()
|
||||||
|
}
|
||||||
|
function findNextList(item, count, direction){
|
||||||
|
if(count == 3) return null
|
||||||
|
var nextItem
|
||||||
|
switch(item){
|
||||||
|
case suggestionsList:nextItem=(direction > 0 ? favoritesList : contactsList);break;
|
||||||
|
case contactsList:nextItem=(direction > 0 ? suggestionsList : favoritesList);break;
|
||||||
|
case favoritesList:nextItem=(direction > 0 ? contactsList : suggestionsList);break;
|
||||||
|
default: return null
|
||||||
|
}
|
||||||
|
if( nextItem.model.count > 0) return nextItem
|
||||||
|
else return findNextList(nextItem, count+1, direction)
|
||||||
|
}
|
||||||
|
function updatePosition(list){
|
||||||
|
var item = list.itemAtIndex(list.currentIndex)
|
||||||
|
var centerPos = list.y - height/2
|
||||||
|
if( item){
|
||||||
|
// For debugging just in case
|
||||||
|
//var listPosition = item.mapToItem(favoriteList, item.x, item.y)
|
||||||
|
//var newPosition = favoriteList.mapToItem(mainItem, listPosition.x, listPosition.y)
|
||||||
|
//console.log("item pos: " +item.x + " / " +item.y)
|
||||||
|
//console.log("fav pos: " +favoriteList.x + " / " +favoriteList.y)
|
||||||
|
//console.log("fav content: " +favoriteList.contentX + " / " +favoriteList.contentY)
|
||||||
|
//console.log("main pos: " +mainItem.x + " / " +mainItem.y)
|
||||||
|
//console.log("main content: " +mainItem.contentX + " / " +mainItem.contentY)
|
||||||
|
//console.log("list pos: " +listPosition.x + " / " +listPosition.y)
|
||||||
|
//console.log("new pos: " +newPosition.x + " / " +newPosition.y)
|
||||||
|
//console.log("header pos: " +headerItem.x + " / " +headerItem.y)
|
||||||
|
//console.log("Moving to " + (headerItem.y+item.y))
|
||||||
|
centerPos += item.y
|
||||||
|
}
|
||||||
|
mainItem.contentY = Math.max(0, centerPos)
|
||||||
|
}
|
||||||
|
Behavior on contentY{
|
||||||
|
NumberAnimation {
|
||||||
|
duration: 500
|
||||||
|
easing.type: Easing.OutExpo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Keys.onPressed: (event)=> {
|
||||||
|
if(!event.accepted){
|
||||||
|
if(event.key == Qt.Key_Up || event.key == Qt.Key_Down){
|
||||||
|
var newItem
|
||||||
|
var direction = (event.key == Qt.Key_Up ? -1 : 1)
|
||||||
|
if(suggestionsList.activeFocus) newItem = findNextList(suggestionsList, 0, direction)
|
||||||
|
if(contactsList.activeFocus) newItem = findNextList(contactsList, 0, direction)
|
||||||
|
if(favoritesList.activeFocus) newItem = findNextList(favoritesList, 0, direction)
|
||||||
|
|
||||||
|
if(newItem){
|
||||||
|
newItem.selectIndex(direction > 0 ? -1 : newItem.model.count - 1)
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (confInfoGui) {
|
||||||
|
for(var i = 0; i < confInfoGui.core.participants.length; ++i) {
|
||||||
|
selectedContacts.push(confInfoGui.core.getParticipantAddressAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: SettingsCpp
|
||||||
|
onLdapConfigChanged: {
|
||||||
|
if (SettingsCpp.syncLdapContacts)
|
||||||
|
magicSearchProxy.forceUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
property MagicSearchProxy mainModel: MagicSearchProxy {
|
||||||
|
id: magicSearchProxy
|
||||||
|
searchText: mainItem.searchText
|
||||||
|
aggregationFlag: LinphoneEnums.MagicSearchAggregation.Friend
|
||||||
|
sourceFlags: mainItem.sourceFlags
|
||||||
|
onModelReset: mainItem.resultsReceived()
|
||||||
|
|
||||||
|
onInitialized: {
|
||||||
|
if(mainItem.searchOnEmpty || searchText != '' ) {
|
||||||
|
mainItem.loading = true
|
||||||
|
forceUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Control.ScrollBar.vertical: ScrollBar {
|
||||||
|
id: scrollbar
|
||||||
|
rightPadding: 8 * DefaultStyle.dp
|
||||||
|
topPadding: mainItem.haveFavorites ? 24 * DefaultStyle.dp : 0 // Avoid to be on top of collapse button
|
||||||
|
|
||||||
|
active: true
|
||||||
|
interactive: true
|
||||||
|
policy: mainItem.contentHeight > mainItem.height ? Control.ScrollBar.AlwaysOn : Control.ScrollBar.AlwaysOff
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ColumnLayout{
|
||||||
|
id: contentsLayout
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
BusyIndicator {
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
Layout.preferredHeight: visible ? 60 * DefaultStyle.dp : 0
|
||||||
|
Layout.preferredWidth: 60 * DefaultStyle.dp
|
||||||
|
indicatorHeight: 60 * DefaultStyle.dp
|
||||||
|
indicatorWidth: 60 * DefaultStyle.dp
|
||||||
|
visible: mainItem.loading
|
||||||
|
indicatorColor: DefaultStyle.main1_500_main
|
||||||
|
}
|
||||||
|
|
||||||
|
ContactListView{
|
||||||
|
id: favoritesList
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: implicitHeight
|
||||||
|
interactive: false
|
||||||
|
highlightText: mainItem.highlightText
|
||||||
|
showActions: mainItem.showActions
|
||||||
|
showInitials: mainItem.showInitials
|
||||||
|
showContactMenu: mainItem.showContactMenu
|
||||||
|
showDefaultAddress: mainItem.showDefaultAddress
|
||||||
|
selectionEnabled: mainItem.selectionEnabled
|
||||||
|
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
||||||
|
selectedContacts: mainItem.selectedContacts
|
||||||
|
title: qsTr('Favoris')
|
||||||
|
|
||||||
|
onHighlightedContactChanged: mainItem.highlightedContact = highlightedContact
|
||||||
|
onContactSelected: (contactGui) => {
|
||||||
|
mainItem.contactSelected(contactGui)
|
||||||
|
}
|
||||||
|
onUpdatePosition: mainItem.updatePosition(favoritesList)
|
||||||
|
onContactDeletionRequested: (contact) => {mainItem.contactDeletionRequested(contact)}
|
||||||
|
onAddContactToSelection: (address) => {mainItem.addContactToSelection(address)}
|
||||||
|
onRemoveContactFromSelection: (index) => {mainItem.removeContactFromSelection(index)}
|
||||||
|
|
||||||
|
property MagicSearchProxy proxy: MagicSearchProxy {
|
||||||
|
parentProxy: mainItem.mainModel
|
||||||
|
filterType: MagicSearchProxy.FilteringTypes.Favorites
|
||||||
|
}
|
||||||
|
model : mainItem.showFavorites && (mainItem.searchBarText == ''|| mainItem.searchBarText == '*')? proxy : []
|
||||||
|
}
|
||||||
|
|
||||||
|
ContactListView{
|
||||||
|
id: contactsList
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: implicitHeight
|
||||||
|
interactive: false
|
||||||
|
highlightText: mainItem.highlightText
|
||||||
|
showActions: mainItem.showActions
|
||||||
|
showInitials: mainItem.showInitials
|
||||||
|
showContactMenu: mainItem.showContactMenu
|
||||||
|
showDefaultAddress: mainItem.showDefaultAddress
|
||||||
|
selectionEnabled: mainItem.selectionEnabled
|
||||||
|
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
||||||
|
selectedContacts: mainItem.selectedContacts
|
||||||
|
title: qsTr('Contacts')
|
||||||
|
|
||||||
|
onHighlightedContactChanged: mainItem.highlightedContact = highlightedContact
|
||||||
|
onContactSelected: (contactGui) => {
|
||||||
|
mainItem.contactSelected(contactGui)
|
||||||
|
}
|
||||||
|
onUpdatePosition: mainItem.updatePosition(contactsList)
|
||||||
|
onContactDeletionRequested: (contact) => {mainItem.contactDeletionRequested(contact)}
|
||||||
|
onAddContactToSelection: (address) => {mainItem.addContactToSelection(address)}
|
||||||
|
onRemoveContactFromSelection: (index) => {mainItem.removeContactFromSelection(index)}
|
||||||
|
|
||||||
|
model:MagicSearchProxy {
|
||||||
|
id: contactsProxy
|
||||||
|
parentProxy: mainItem.mainModel
|
||||||
|
filterType: MagicSearchProxy.FilteringTypes.App | (mainItem.searchText != '*' && mainItem.searchText != '' || SettingsCpp.syncLdapContacts ? MagicSearchProxy.FilteringTypes.Ldap : 0)
|
||||||
|
initialDisplayItems: 20
|
||||||
|
displayItemsStep: 5
|
||||||
|
onLocalFriendCreated: (index) => {
|
||||||
|
contactsList.selectIndex(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ContactListView{
|
||||||
|
id: suggestionsList
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: implicitHeight
|
||||||
|
interactive: false
|
||||||
|
showInitials: false
|
||||||
|
highlightText: mainItem.highlightText
|
||||||
|
showActions: mainItem.showActions
|
||||||
|
showContactMenu: mainItem.showContactMenu
|
||||||
|
showDefaultAddress: mainItem.showDefaultAddress
|
||||||
|
selectionEnabled: mainItem.selectionEnabled
|
||||||
|
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
||||||
|
selectedContacts: mainItem.selectedContacts
|
||||||
|
title: qsTr('Suggestions')
|
||||||
|
|
||||||
|
onHighlightedContactChanged: mainItem.highlightedContact = highlightedContact
|
||||||
|
onContactSelected: (contactGui) => {
|
||||||
|
mainItem.contactSelected(contactGui)
|
||||||
|
}
|
||||||
|
onUpdatePosition: mainItem.updatePosition(suggestionsList)
|
||||||
|
onContactDeletionRequested: (contact) => {mainItem.contactDeletionRequested(contact)}
|
||||||
|
onAddContactToSelection: (address) => {mainItem.addContactToSelection(address)}
|
||||||
|
onRemoveContactFromSelection: (index) => {mainItem.removeContactFromSelection(index)}
|
||||||
|
|
||||||
|
model:MagicSearchProxy {
|
||||||
|
id: suggestionsProxy
|
||||||
|
parentProxy: mainItem.mainModel
|
||||||
|
filterType: mainItem.hideSuggestions ? MagicSearchProxy.FilteringTypes.None : MagicSearchProxy.FilteringTypes.Other
|
||||||
|
initialDisplayItems: 0
|
||||||
|
displayItemsStep: 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,7 @@ import ConstantsCpp 1.0
|
||||||
import SettingsCpp
|
import SettingsCpp
|
||||||
FocusScope {
|
FocusScope {
|
||||||
id: mainItem
|
id: mainItem
|
||||||
implicitHeight: 56 * DefaultStyle.dp
|
implicitHeight: visible ? 56 * DefaultStyle.dp : 0
|
||||||
property var searchResultItem
|
property var searchResultItem
|
||||||
property bool showInitials: true // Display Initials of Display name.
|
property bool showInitials: true // Display Initials of Display name.
|
||||||
property bool showDefaultAddress: true // Display address below display name.
|
property bool showDefaultAddress: true // Display address below display name.
|
||||||
|
|
@ -21,10 +21,8 @@ FocusScope {
|
||||||
property bool selectionEnabled: true // Contact can be selected
|
property bool selectionEnabled: true // Contact can be selected
|
||||||
property bool multiSelectionEnabled: false //Multiple items can be selected.
|
property bool multiSelectionEnabled: false //Multiple items can be selected.
|
||||||
property list<string> selectedContacts // List of default address on selected contacts.
|
property list<string> selectedContacts // List of default address on selected contacts.
|
||||||
property int selectedContactCount: selectedContacts.length
|
|
||||||
property bool isSelected: false // selected in list => currentIndex == index
|
property bool isSelected: false // selected in list => currentIndex == index
|
||||||
|
|
||||||
|
|
||||||
property var previousInitial // Use directly previous initial
|
property var previousInitial // Use directly previous initial
|
||||||
property int itemsRightMargin: 39 * DefaultStyle.dp
|
property int itemsRightMargin: 39 * DefaultStyle.dp
|
||||||
|
|
||||||
|
|
@ -32,15 +30,8 @@ FocusScope {
|
||||||
property string initial: displayName ? displayName[0].toLocaleLowerCase(ConstantsCpp.DefaultLocale) : ''
|
property string initial: displayName ? displayName[0].toLocaleLowerCase(ConstantsCpp.DefaultLocale) : ''
|
||||||
|
|
||||||
signal clicked(var mouse)
|
signal clicked(var mouse)
|
||||||
signal contactStarredChanged()
|
|
||||||
signal contactDeletionRequested(FriendGui contact)
|
signal contactDeletionRequested(FriendGui contact)
|
||||||
|
|
||||||
Connections {
|
|
||||||
enabled: searchResultItem.core
|
|
||||||
target: searchResultItem.core
|
|
||||||
function onStarredChanged() { mainItem.contactStarredChanged()}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: initial
|
id: initial
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|
@ -63,7 +54,8 @@ FocusScope {
|
||||||
anchors.left: initial.visible ? initial.right : parent.left
|
anchors.left: initial.visible ? initial.right : parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: mainItem.itemsRightMargin
|
anchors.rightMargin: mainItem.itemsRightMargin
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
spacing: 16 * DefaultStyle.dp
|
spacing: 16 * DefaultStyle.dp
|
||||||
z: 1
|
z: 1
|
||||||
Avatar {
|
Avatar {
|
||||||
|
|
@ -106,19 +98,11 @@ FocusScope {
|
||||||
spacing: visible ? 16 * DefaultStyle.dp : 0
|
spacing: visible ? 16 * DefaultStyle.dp : 0
|
||||||
EffectImage {
|
EffectImage {
|
||||||
id: isSelectedCheck
|
id: isSelectedCheck
|
||||||
// visible: mainItem.multiSelectionEnabled && (mainItem.confInfoGui.core.getParticipantIndex(searchResultItem.core.defaultAddress) != -1)
|
|
||||||
visible: mainItem.multiSelectionEnabled && (mainItem.selectedContacts.indexOf(searchResultItem.core.defaultAddress) != -1)
|
visible: mainItem.multiSelectionEnabled && (mainItem.selectedContacts.indexOf(searchResultItem.core.defaultAddress) != -1)
|
||||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||||
Layout.preferredHeight: 24 * DefaultStyle.dp
|
Layout.preferredHeight: 24 * DefaultStyle.dp
|
||||||
imageSource: AppIcons.check
|
imageSource: AppIcons.check
|
||||||
colorizationColor: DefaultStyle.main1_500_main
|
colorizationColor: DefaultStyle.main1_500_main
|
||||||
Connections {
|
|
||||||
target: mainItem
|
|
||||||
// onParticipantsChanged: isSelectedCheck.visible = mainItem.confInfoGui.core.getParticipantIndex(searchResultItem.core.defaultAddress) != -1
|
|
||||||
function onSelectedContactCountChanged(){
|
|
||||||
isSelectedCheck.visible = (mainItem.selectedContacts.indexOf(searchResultItem.core.defaultAddress) != -1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RowLayout{
|
RowLayout{
|
||||||
id: actionButtons
|
id: actionButtons
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import SettingsCpp
|
||||||
ListView {
|
ListView {
|
||||||
id: mainItem
|
id: mainItem
|
||||||
|
|
||||||
|
property string title
|
||||||
property bool showInitials: true // Display Initials of Display name.
|
property bool showInitials: true // Display Initials of Display name.
|
||||||
property bool showDefaultAddress: true // Display address below display name.
|
property bool showDefaultAddress: true // Display address below display name.
|
||||||
property bool showActions: false // Display actions layout (call buttons)
|
property bool showActions: false // Display actions layout (call buttons)
|
||||||
|
|
@ -25,141 +26,73 @@ ListView {
|
||||||
property bool selectionEnabled: true // Contact can be selected
|
property bool selectionEnabled: true // Contact can be selected
|
||||||
property bool multiSelectionEnabled: false //Multiple items can be selected.
|
property bool multiSelectionEnabled: false //Multiple items can be selected.
|
||||||
property list<string> selectedContacts // List of default address on selected contacts.
|
property list<string> selectedContacts // List of default address on selected contacts.
|
||||||
property FriendGui selectedContact//: model.getAt(currentIndex) || null
|
property FriendGui highlightedContact
|
||||||
|
|
||||||
property bool searchOnInitialization: false
|
|
||||||
property bool loading: false
|
|
||||||
property bool pauseSearch: false // true = don't search on text change
|
|
||||||
|
|
||||||
// Model properties
|
// Model properties
|
||||||
// set searchBarText without specifying a model to bold
|
// set searchBarText without specifying a model to bold
|
||||||
// matching names
|
// matching names
|
||||||
property string searchBarText
|
property string searchText
|
||||||
property string searchText// Binding is done on searchBarTextChanged
|
|
||||||
property ConferenceInfoGui confInfoGui
|
property ConferenceInfoGui confInfoGui
|
||||||
|
|
||||||
property bool haveFavorites: false
|
property bool haveFavorites: false
|
||||||
property bool haveContacts: count > 0 || (showFavorites && headerItem.list.count > 0)
|
property bool haveContacts: count > 0
|
||||||
property int sectionsPixelSize: 16 * DefaultStyle.dp
|
property int sectionsPixelSize: 16 * DefaultStyle.dp
|
||||||
property int sectionsWeight: 800 * DefaultStyle.dp
|
property int sectionsWeight: 800 * DefaultStyle.dp
|
||||||
property int sectionsSpacing: 18 * DefaultStyle.dp
|
property int sectionsSpacing: 18 * DefaultStyle.dp
|
||||||
|
|
||||||
property int itemsRightMargin: 39 * DefaultStyle.dp
|
property int itemsRightMargin: 39 * DefaultStyle.dp
|
||||||
|
property bool expanded: true
|
||||||
|
|
||||||
signal resultsReceived()
|
signal resultsReceived()
|
||||||
signal contactStarredChanged()
|
|
||||||
signal contactDeletionRequested(FriendGui contact)
|
signal contactDeletionRequested(FriendGui contact)
|
||||||
signal contactAddedToSelection(string address)
|
signal contactSelected(FriendGui contact) // Click/Space/Enter
|
||||||
signal contactRemovedFromSelection(string address)
|
signal addContactToSelection(var address)
|
||||||
signal contactClicked(FriendGui contact)
|
signal removeContactFromSelection(var indexInSelection)
|
||||||
|
signal updatePosition()
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
highlightFollowsCurrentItem: true
|
highlightFollowsCurrentItem: false
|
||||||
cacheBuffer: 400
|
cacheBuffer: 400
|
||||||
// Binding loop hack
|
implicitHeight: contentHeight + headerItem?.height
|
||||||
onContentHeightChanged: Qt.callLater(function(){cacheBuffer = Math.max(0,contentHeight)})
|
spacing: 4 * DefaultStyle.dp
|
||||||
|
|
||||||
function selectContact(address) {
|
property bool _moveToIndex: false
|
||||||
var index = magicSearchProxy.findFriendIndexByAddress(address)
|
|
||||||
if (index != -1) {
|
|
||||||
mainItem.currentIndex = index
|
|
||||||
}
|
|
||||||
return index
|
|
||||||
}
|
|
||||||
function addContactToSelection(address) {
|
|
||||||
if (multiSelectionEnabled) {
|
|
||||||
var indexInSelection = selectedContacts.indexOf(address)
|
|
||||||
if (indexInSelection == -1) {
|
|
||||||
selectedContacts.push(address)
|
|
||||||
contactAddedToSelection(address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function removeContactFromSelection(indexInSelection) {
|
|
||||||
var addressToRemove = selectedContacts[indexInSelection]
|
|
||||||
if (indexInSelection != -1) {
|
|
||||||
selectedContacts.splice(indexInSelection, 1)
|
|
||||||
contactRemovedFromSelection(addressToRemove)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function removeSelectedContactByAddress(address) {
|
|
||||||
var index = selectedContacts.indexOf(address)
|
|
||||||
if (index != -1) {
|
|
||||||
selectedContacts.splice(index, 1)
|
|
||||||
contactRemovedFromSelection(address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function haveAddress(address){
|
|
||||||
var index = magicSearchProxy.findFriendIndexByAddress(address)
|
|
||||||
return index != -1
|
|
||||||
}
|
|
||||||
|
|
||||||
onResultsReceived: {
|
function selectIndex(index){
|
||||||
loading = false
|
if(mainItem.expanded && index >= 0){
|
||||||
mainItem.positionViewAtBeginning()
|
mainItem.currentIndex = index
|
||||||
}
|
var item = itemAtIndex(mainItem.currentIndex)
|
||||||
onSearchBarTextChanged: {
|
if(item){// Item is ready and available
|
||||||
loading = true
|
mainItem.highlightedContact = item.searchResultItem
|
||||||
if(!pauseSearch) {
|
item.forceActiveFocus()
|
||||||
searchText = searchBarText.length === 0 ? "*" : searchBarText
|
updatePosition()
|
||||||
|
}else{// Move on the next items load.
|
||||||
|
_moveToIndex = true
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
mainItem.currentIndex = -1
|
||||||
|
mainItem.highlightedContact = null
|
||||||
|
if(headerItem) headerItem.forceActiveFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onPauseSearchChanged: {
|
onCountChanged: if(_moveToIndex >= 0 && count > mainItem.currentIndex ){
|
||||||
if(!pauseSearch){
|
_moveToIndex = false
|
||||||
searchText = searchBarText.length === 0 ? "*" : searchBarText
|
selectIndex(mainItem.currentIndex)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
onAtYEndChanged: if(atYEnd) magicSearchProxy.displayMore()
|
onContactSelected: updatePosition()
|
||||||
keyNavigationEnabled: false
|
keyNavigationEnabled: false
|
||||||
Keys.onPressed: (event)=> {
|
Keys.onPressed: (event)=> {
|
||||||
if(header.activeFocus) return;
|
|
||||||
if(event.key == Qt.Key_Up || event.key == Qt.Key_Down){
|
if(event.key == Qt.Key_Up || event.key == Qt.Key_Down){
|
||||||
if (currentIndex == 0 && event.key == Qt.Key_Up) {
|
if(event.key == Qt.Key_Up && !headerItem.activeFocus) {
|
||||||
if( headerItem.list.count > 0) {
|
if(currentIndex >= 0 ) {
|
||||||
mainItem.highlightFollowsCurrentItem = false
|
selectIndex(mainItem.currentIndex-1)
|
||||||
currentIndex = -1
|
|
||||||
headerItem.list.currentIndex = headerItem.list.count -1
|
|
||||||
var item = headerItem.list.itemAtIndex(headerItem.list.currentIndex)
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
headerItem.updatePosition()
|
|
||||||
event.accepted = true;
|
|
||||||
}else{
|
|
||||||
mainItem.currentIndex = mainItem.count - 1
|
|
||||||
var item = itemAtIndex(mainItem.currentIndex)
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
}
|
}
|
||||||
}else if(currentIndex >= mainItem.count -1 && event.key == Qt.Key_Down){
|
}else if(event.key == Qt.Key_Down && mainItem.expanded){
|
||||||
if( headerItem.list.count > 0) {
|
if(currentIndex < model.count - 1) {
|
||||||
mainItem.highlightFollowsCurrentItem = false
|
selectIndex(mainItem.currentIndex+1)
|
||||||
mainItem.currentIndex = -1
|
|
||||||
headerItem.list.currentIndex = 0
|
|
||||||
var item = headerItem.list.itemAtIndex(headerItem.list.currentIndex)
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
headerItem.updatePosition()
|
|
||||||
event.accepted = true;
|
|
||||||
}else{
|
|
||||||
mainItem.currentIndex = 0
|
|
||||||
var item = itemAtIndex(mainItem.currentIndex)
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
event.accepted = true;
|
event.accepted = true;
|
||||||
}
|
}
|
||||||
}else if(event.key == Qt.Key_Up){
|
|
||||||
mainItem.highlightFollowsCurrentItem = true
|
|
||||||
var item = itemAtIndex(--mainItem.currentIndex)
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
event.accepted = true;
|
|
||||||
}else if(event.key == Qt.Key_Down){
|
|
||||||
mainItem.highlightFollowsCurrentItem = true
|
|
||||||
var item = itemAtIndex(++mainItem.currentIndex)
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -178,307 +111,95 @@ ListView {
|
||||||
magicSearchProxy.forceUpdate()
|
magicSearchProxy.forceUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Control.ScrollBar.vertical: ScrollBar {
|
|
||||||
id: scrollbar
|
|
||||||
rightPadding: 8 * DefaultStyle.dp
|
|
||||||
topPadding: mainItem.haveFavorites ? 24 * DefaultStyle.dp : 0 // Avoid to be on top of collapse button
|
|
||||||
|
|
||||||
active: true
|
|
||||||
interactive: true
|
|
||||||
policy: mainItem.contentHeight > mainItem.height ? Control.ScrollBar.AlwaysOn : Control.ScrollBar.AlwaysOff
|
|
||||||
}
|
|
||||||
|
|
||||||
model: MagicSearchProxy {
|
|
||||||
id: magicSearchProxy
|
|
||||||
searchText: mainItem.searchText
|
|
||||||
aggregationFlag: LinphoneEnums.MagicSearchAggregation.Friend
|
|
||||||
sourceFlags: mainItem.sourceFlags
|
|
||||||
|
|
||||||
hideSuggestions: mainItem.hideSuggestions
|
|
||||||
showLdapContacts: mainItem.searchText != '*' && mainItem.searchText != '' || SettingsCpp.syncLdapContacts
|
|
||||||
initialDisplayItems: 20
|
|
||||||
onLocalFriendCreated: (index) => {
|
|
||||||
var item = itemAtIndex(index)
|
|
||||||
if(item){
|
|
||||||
mainItem.currentIndex = index
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onInitialized: {
|
|
||||||
mainItem.loading = true
|
|
||||||
magicSearchProxy.forceUpdate()
|
|
||||||
}
|
|
||||||
onModelReset: mainItem.resultsReceived()
|
|
||||||
}
|
|
||||||
|
|
||||||
section.property: "isStored"
|
|
||||||
//section.criteria: ViewSection.FirstCharacter
|
|
||||||
section.delegate: Item{
|
|
||||||
width: mainItem.width
|
|
||||||
height: textItem.implicitHeight + sectionsSpacing * 2
|
|
||||||
required property bool section
|
|
||||||
Text {
|
|
||||||
id: textItem
|
|
||||||
anchors.fill: parent
|
|
||||||
text: section ? qsTr("Contacts") : qsTr("Suggestions")
|
|
||||||
horizontalAlignment: Text.AlignLeft
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
font {
|
|
||||||
pixelSize: sectionsPixelSize
|
|
||||||
weight: sectionsWeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
header: FocusScope{
|
header: FocusScope{
|
||||||
id: headerItem
|
id: headerItem
|
||||||
width: mainItem.width
|
width: mainItem.width
|
||||||
height: favoritesContents.implicitHeight
|
height: headerContents.implicitHeight
|
||||||
property alias list: favoriteList
|
onActiveFocusChanged: {
|
||||||
|
if(activeFocus) mainItem.updatePosition()
|
||||||
|
}
|
||||||
|
|
||||||
// Hack because changing currentindex change focus.
|
ColumnLayout {
|
||||||
Timer{
|
id: headerContents
|
||||||
id: focusDelay
|
width: parent.width
|
||||||
interval: 10
|
spacing: mainItem.count > 0 ? sectionsSpacing : 0
|
||||||
onTriggered: {
|
Item{// Do not use directly RowLayout : there is an issue where the layout doesn't update on visible
|
||||||
mainItem.highlightFollowsCurrentItem = !headerItem.activeFocus
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: mainItem.count > 0 ? headerTitleLayout.implicitHeight : 0
|
||||||
|
RowLayout {
|
||||||
|
id: headerTitleLayout
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: 0
|
||||||
|
// Need this because it can stay at 0 on display without manual relayouting (moving position, resize)
|
||||||
|
visible: mainItem.count > 0
|
||||||
|
Text {
|
||||||
|
text: mainItem.title
|
||||||
|
font {
|
||||||
|
pixelSize: sectionsPixelSize
|
||||||
|
weight: sectionsWeight
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
Item {
|
||||||
onActiveFocusChanged:focusDelay.restart()
|
|
||||||
//---------------------------------------------------
|
|
||||||
|
|
||||||
function updatePosition(){
|
|
||||||
var item = favoriteList.itemAtIndex(favoriteList.currentIndex)
|
|
||||||
if( item){
|
|
||||||
// For debugging just in case
|
|
||||||
//var listPosition = item.mapToItem(favoriteList, item.x, item.y)
|
|
||||||
//var newPosition = favoriteList.mapToItem(mainItem, listPosition.x, listPosition.y)
|
|
||||||
//console.log("item pos: " +item.x + " / " +item.y)
|
|
||||||
//console.log("fav pos: " +favoriteList.x + " / " +favoriteList.y)
|
|
||||||
//console.log("fav content: " +favoriteList.contentX + " / " +favoriteList.contentY)
|
|
||||||
//console.log("main pos: " +mainItem.x + " / " +mainItem.y)
|
|
||||||
//console.log("main content: " +mainItem.contentX + " / " +mainItem.contentY)
|
|
||||||
//console.log("list pos: " +listPosition.x + " / " +listPosition.y)
|
|
||||||
//console.log("new pos: " +newPosition.x + " / " +newPosition.y)
|
|
||||||
//console.log("header pos: " +headerItem.x + " / " +headerItem.y)
|
|
||||||
//console.log("Moving to " + (headerItem.y+item.y))
|
|
||||||
mainItem.contentY = headerItem.y+item.y
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: favoritesContents
|
|
||||||
width: parent.width
|
|
||||||
spacing: mainItem.haveFavorites ? sectionsSpacing : 0
|
|
||||||
BusyIndicator {
|
|
||||||
Layout.alignment: Qt.AlignCenter
|
|
||||||
Layout.preferredHeight: visible ? 60 * DefaultStyle.dp : 0
|
|
||||||
Layout.preferredWidth: 60 * DefaultStyle.dp
|
|
||||||
indicatorHeight: 60 * DefaultStyle.dp
|
|
||||||
indicatorWidth: 60 * DefaultStyle.dp
|
|
||||||
visible: mainItem.loading
|
|
||||||
indicatorColor: DefaultStyle.main1_500_main
|
|
||||||
|
|
||||||
}
|
|
||||||
Item{// Do not use directly RowLayout : there is an issue where the layout doesn't update on visible
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: mainItem.haveFavorites ? favoriteTitle.implicitHeight : 0
|
|
||||||
RowLayout {
|
|
||||||
id: favoriteTitle
|
|
||||||
anchors.fill: parent
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
// Need this because it can stay at 0 on display without manual relayouting (moving position, resize)
|
|
||||||
visible: mainItem.haveFavorites
|
|
||||||
onVisibleChanged: if(visible) {
|
|
||||||
Qt.callLater(mainItem.positionViewAtBeginning)// If not later, the view will not move to favoris at startup
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
//Layout.fillHeight: true
|
|
||||||
text: qsTr("Favoris")
|
|
||||||
font {
|
|
||||||
pixelSize: sectionsPixelSize
|
|
||||||
weight: sectionsWeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: favoriteExpandButton
|
|
||||||
background: Item{}
|
|
||||||
icon.source: favoriteList.visible ? AppIcons.upArrow : AppIcons.downArrow
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.preferredWidth: height
|
|
||||||
//Layout.preferredWidth: 24 * DefaultStyle.dp
|
|
||||||
//Layout.preferredHeight: 24 * DefaultStyle.dp
|
|
||||||
Layout.rightMargin: 23 * DefaultStyle.dp
|
|
||||||
icon.width: 24 * DefaultStyle.dp
|
|
||||||
icon.height: 24 * DefaultStyle.dp
|
|
||||||
focus: true
|
|
||||||
onClicked: favoriteList.visible = !favoriteList.visible
|
|
||||||
KeyNavigation.down: favoriteList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ListView{
|
Button {
|
||||||
id: favoriteList
|
id: headerExpandButton
|
||||||
Layout.fillWidth: true
|
background: Item{}
|
||||||
Layout.preferredHeight: count > 0 ? contentHeight : 0// Show full and avoid scrolling
|
icon.source: mainItem.expanded ? AppIcons.upArrow : AppIcons.downArrow
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
Layout.rightMargin: 23 * DefaultStyle.dp
|
||||||
onCountChanged: mainItem.haveFavorites = count > 0
|
icon.width: 24 * DefaultStyle.dp
|
||||||
Keys.onPressed: (event)=> {
|
icon.height: 24 * DefaultStyle.dp
|
||||||
if(event.key == Qt.Key_Up || event.key == Qt.Key_Down) {
|
focus: true
|
||||||
if (favoriteList.currentIndex == 0 && event.key == Qt.Key_Up) {
|
onClicked: mainItem.expanded = !mainItem.expanded
|
||||||
if( mainItem.count > 0) {
|
|
||||||
mainItem.highlightFollowsCurrentItem = true
|
|
||||||
favoriteList.currentIndex = -1
|
|
||||||
mainItem.currentIndex = mainItem.count-1
|
|
||||||
var item = mainItem.itemAtIndex(mainItem.currentIndex)
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
event.accepted = true;
|
|
||||||
}else{
|
|
||||||
favoriteList.currentIndex = favoriteList.count - 1
|
|
||||||
var item = itemAtIndex(favoriteList.currentIndex)
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
}else if(currentIndex >= favoriteList.count -1 && event.key == Qt.Key_Down) {
|
|
||||||
if( mainItem.count > 0) {
|
|
||||||
mainItem.highlightFollowsCurrentItem = true
|
|
||||||
favoriteList.currentIndex = -1
|
|
||||||
mainItem.currentIndex = 0
|
|
||||||
var item = mainItem.itemAtIndex(mainItem.currentIndex)
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
event.accepted = true;
|
|
||||||
}else{
|
|
||||||
favoriteList.currentIndex = 0
|
|
||||||
var item = itemAtIndex(favoriteList.currentIndex)
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
}else if(event.key == Qt.Key_Up){
|
|
||||||
mainItem.highlightFollowsCurrentItem = false
|
|
||||||
var item = itemAtIndex(--favoriteList.currentIndex)
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
headerItem.updatePosition()
|
|
||||||
event.accepted = true;
|
|
||||||
}else if(event.key == Qt.Key_Down){
|
|
||||||
mainItem.highlightFollowsCurrentItem = false
|
|
||||||
var item = itemAtIndex(++favoriteList.currentIndex)
|
|
||||||
mainItem.selectedContact = item.searchResultItem
|
|
||||||
item.forceActiveFocus()
|
|
||||||
headerItem.updatePosition()
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
property MagicSearchProxy proxy: MagicSearchProxy{
|
|
||||||
parentProxy: mainItem.model
|
|
||||||
showFavoritesOnly: true
|
|
||||||
hideSuggestions: mainItem.hideSuggestions
|
|
||||||
}
|
|
||||||
model : showFavorites && mainItem.searchBarText == '' ? proxy : []
|
|
||||||
delegate: ContactListItem{
|
|
||||||
width: favoriteList.width
|
|
||||||
focus: true
|
|
||||||
|
|
||||||
searchResultItem: $modelData
|
|
||||||
showInitials: mainItem.showInitials
|
|
||||||
showDefaultAddress: mainItem.showDefaultAddress
|
|
||||||
showActions: mainItem.showActions
|
|
||||||
showContactMenu: mainItem.showContactMenu
|
|
||||||
highlightText: mainItem.highlightText
|
|
||||||
|
|
||||||
displayNameCapitalization: mainItem.displayNameCapitalization
|
|
||||||
itemsRightMargin: mainItem.itemsRightMargin
|
|
||||||
selectionEnabled: mainItem.selectionEnabled
|
|
||||||
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
|
||||||
selectedContacts: mainItem.selectedContacts
|
|
||||||
isSelected: mainItem.selectedContact && mainItem.selectedContact.core == searchResultItem.core
|
|
||||||
previousInitial: ''//favoriteList.count > 0 ? favoriteList.itemAtIndex(index-1)?.initial : '' // Binding on count
|
|
||||||
initial: '' // Hide initials but keep space
|
|
||||||
|
|
||||||
onIsSelectedChanged: if(isSelected) favoriteList.currentIndex = index
|
|
||||||
onContactStarredChanged: mainItem.contactStarredChanged()
|
|
||||||
onContactDeletionRequested: (contact) => mainItem.contactDeletionRequested(contact)
|
|
||||||
onClicked: (mouse) => {
|
|
||||||
mainItem.highlightFollowsCurrentItem = false
|
|
||||||
favoriteList.currentIndex = index
|
|
||||||
mainItem.selectedContact = searchResultItem
|
|
||||||
forceActiveFocus()
|
|
||||||
headerItem.updatePosition()
|
|
||||||
if (mainItem.multiSelectionEnabled) {
|
|
||||||
var indexInSelection = mainItem.selectedContacts.indexOf(searchResultItem.core.defaultAddress)
|
|
||||||
if (indexInSelection == -1) {
|
|
||||||
mainItem.addContactToSelection(searchResultItem.core.defaultAddress)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mainItem.removeContactFromSelection(indexInSelection, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mainItem.contactClicked(searchResultItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delegate: ContactListItem{
|
delegate: ContactListItem{
|
||||||
id: contactItem
|
id: contactItem
|
||||||
width: mainItem.width
|
width: mainItem.width
|
||||||
focus: true
|
focus: true
|
||||||
|
visible: mainItem.expanded
|
||||||
searchResultItem: $modelData
|
searchResultItem: $modelData
|
||||||
showInitials: mainItem.showInitials && isStored
|
showInitials: mainItem.showInitials && isStored
|
||||||
showDefaultAddress: mainItem.showDefaultAddress
|
showDefaultAddress: mainItem.showDefaultAddress
|
||||||
showActions: mainItem.showActions
|
showActions: mainItem.showActions
|
||||||
showContactMenu: searchResultItem.core.isStored
|
showContactMenu: searchResultItem.core.isStored
|
||||||
|
|
||||||
highlightText: mainItem.highlightText
|
highlightText: mainItem.highlightText
|
||||||
|
|
||||||
displayNameCapitalization: mainItem.displayNameCapitalization
|
displayNameCapitalization: mainItem.displayNameCapitalization
|
||||||
itemsRightMargin: mainItem.itemsRightMargin
|
|
||||||
|
|
||||||
selectionEnabled: mainItem.selectionEnabled
|
selectionEnabled: mainItem.selectionEnabled
|
||||||
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
multiSelectionEnabled: mainItem.multiSelectionEnabled
|
||||||
selectedContacts: mainItem.selectedContacts
|
selectedContacts: mainItem.selectedContacts
|
||||||
isSelected: mainItem.selectedContact && mainItem.selectedContact.core == searchResultItem.core
|
isSelected: mainItem.highlightedContact && mainItem.highlightedContact.core == searchResultItem.core
|
||||||
previousInitial: mainItem.itemAtIndex(index-1)?.initial
|
previousInitial: mainItem.itemAtIndex(index-1)?.initial
|
||||||
|
itemsRightMargin: mainItem.itemsRightMargin
|
||||||
|
|
||||||
onIsSelectedChanged: if(isSelected) mainItem.currentIndex = index
|
onIsSelectedChanged: if(isSelected) mainItem.currentIndex = index
|
||||||
onContactStarredChanged: mainItem.contactStarredChanged()
|
|
||||||
onContactDeletionRequested: (contact) => mainItem.contactDeletionRequested(contact)
|
onContactDeletionRequested: (contact) => mainItem.contactDeletionRequested(contact)
|
||||||
|
|
||||||
onClicked: (mouse) => {
|
onClicked: (mouse) => {
|
||||||
mainItem.highlightFollowsCurrentItem = true
|
|
||||||
if (mouse && mouse.button == Qt.RightButton) {
|
if (mouse && mouse.button == Qt.RightButton) {
|
||||||
friendPopup.open()
|
friendPopup.open()
|
||||||
} else {
|
} else {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
if(mainItem.selectedContact && mainItem.selectedContact.core != contactItem.searchResultItem.core)
|
mainItem.highlightedContact = contactItem.searchResultItem
|
||||||
headerItem.list.currentIndex = -1
|
if (mainItem.multiSelectionEnabled) {
|
||||||
mainItem.selectedContact = contactItem.searchResultItem
|
var indexInSelection = mainItem.selectedContacts.indexOf(searchResultItem.core.defaultAddress)
|
||||||
if (mainItem.multiSelectionEnabled) {
|
if (indexInSelection == -1) {
|
||||||
var indexInSelection = mainItem.selectedContacts.indexOf(searchResultItem.core.defaultAddress)
|
mainItem.addContactToSelection(searchResultItem.core.defaultAddress)
|
||||||
if (indexInSelection == -1) {
|
}
|
||||||
mainItem.addContactToSelection(searchResultItem.core.defaultAddress)
|
else {
|
||||||
}
|
mainItem.removeContactFromSelection(indexInSelection)
|
||||||
else {
|
}
|
||||||
mainItem.removeContactFromSelection(indexInSelection, 1)
|
}
|
||||||
}
|
mainItem.contactSelected(searchResultItem)
|
||||||
}
|
}
|
||||||
mainItem.contactClicked(searchResultItem)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ FocusScope {
|
||||||
Layout.preferredHeight: 44 * DefaultStyle.dp
|
Layout.preferredHeight: 44 * DefaultStyle.dp
|
||||||
padding: 0
|
padding: 0
|
||||||
KeyNavigation.up: searchBar
|
KeyNavigation.up: searchBar
|
||||||
KeyNavigation.down: contactLoader.item
|
KeyNavigation.down: contactList
|
||||||
onClicked: mainItem.groupCallCreationRequested()
|
onClicked: mainItem.groupCallCreationRequested()
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
@ -127,23 +127,13 @@ FocusScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loader{
|
AllContactListView{
|
||||||
// This is a hack for an incomprehensible behavior on sections title where they doesn't match with their delegate and can be unordered after resetting models.
|
id: contactList
|
||||||
id: contactLoader
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
property string t: searchBar.text
|
searchBarText: searchBar.text
|
||||||
onTChanged: {
|
onContactSelected: (contact) => {
|
||||||
contactLoader.active = false
|
mainItem.contactClicked(contact)
|
||||||
Qt.callLater(function(){contactLoader.active=true})
|
|
||||||
}
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
sourceComponent: ContactListView{
|
|
||||||
id: contactList
|
|
||||||
searchBarText: searchBar.text
|
|
||||||
onContactClicked: (contact) => {
|
|
||||||
mainItem.contactClicked(contact)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ FocusScope{
|
||||||
id: mainItem
|
id: mainItem
|
||||||
|
|
||||||
property string placeHolderText: qsTr("Rechercher des contacts")
|
property string placeHolderText: qsTr("Rechercher des contacts")
|
||||||
property list<string> selectedParticipants//: contactLoader.item ? contactLoader.item.selectedContacts
|
property list<string> selectedParticipants
|
||||||
property int selectedParticipantsCount: selectedParticipants.length
|
property int selectedParticipantsCount: selectedParticipants.length
|
||||||
property ConferenceInfoGui conferenceInfoGui
|
property ConferenceInfoGui conferenceInfoGui
|
||||||
property color searchBarColor: DefaultStyle.grey_100
|
property color searchBarColor: DefaultStyle.grey_100
|
||||||
|
|
@ -32,7 +32,6 @@ FocusScope{
|
||||||
width: mainItem.width
|
width: mainItem.width
|
||||||
model: mainItem.selectedParticipants
|
model: mainItem.selectedParticipants
|
||||||
clip: true
|
clip: true
|
||||||
focus: participantList.count > 0
|
|
||||||
Keys.onPressed: (event) => {
|
Keys.onPressed: (event) => {
|
||||||
if(currentIndex <=0 && event.key == Qt.Key_Up){
|
if(currentIndex <=0 && event.key == Qt.Key_Up){
|
||||||
nextItemInFocusChain(false).forceActiveFocus()
|
nextItemInFocusChain(false).forceActiveFocus()
|
||||||
|
|
@ -67,7 +66,7 @@ FocusScope{
|
||||||
icon.height: 24 * DefaultStyle.dp
|
icon.height: 24 * DefaultStyle.dp
|
||||||
focus: true
|
focus: true
|
||||||
contentImageColor: DefaultStyle.main1_500_main
|
contentImageColor: DefaultStyle.main1_500_main
|
||||||
onClicked: if(contactLoader.item) contactLoader.item.removeSelectedContactByAddress(modelData)
|
onClicked: contactList.removeSelectedContactByAddress(modelData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -95,13 +94,13 @@ FocusScope{
|
||||||
KeyNavigation.up: participantList.count > 0
|
KeyNavigation.up: participantList.count > 0
|
||||||
? participantList
|
? participantList
|
||||||
: nextItemInFocusChain(false)
|
: nextItemInFocusChain(false)
|
||||||
KeyNavigation.down: contactLoader.item
|
KeyNavigation.down: contactList
|
||||||
}
|
}
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: content
|
id: content
|
||||||
spacing: 15 * DefaultStyle.dp
|
spacing: 15 * DefaultStyle.dp
|
||||||
Text {
|
Text {
|
||||||
visible: !contactLoader.item?.loading && contactLoader.item?.count === 0
|
visible: !contactList.loading && contactList.count === 0
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.topMargin: 137 * DefaultStyle.dp
|
Layout.topMargin: 137 * DefaultStyle.dp
|
||||||
text: qsTr("Aucun contact%1").arg(searchBar.text.length !== 0 ? " correspondant" : "")
|
text: qsTr("Aucun contact%1").arg(searchBar.text.length !== 0 ? " correspondant" : "")
|
||||||
|
|
@ -110,33 +109,21 @@ FocusScope{
|
||||||
weight: 800 * DefaultStyle.dp
|
weight: 800 * DefaultStyle.dp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loader{
|
AllContactListView{
|
||||||
// This is a hack for an incomprehensible behavior on sections title where they doesn't match with their delegate and can be unordered after resetting models.
|
id: contactList
|
||||||
id: contactLoader
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
property string t: searchBar.text
|
itemsRightMargin: 28 * DefaultStyle.dp
|
||||||
onTChanged: {
|
multiSelectionEnabled: true
|
||||||
contactLoader.active = false
|
showContactMenu: false
|
||||||
Qt.callLater(function(){contactLoader.active=true})
|
confInfoGui: mainItem.conferenceInfoGui
|
||||||
}
|
selectedContacts: mainItem.selectedParticipants
|
||||||
//-------------------------------------------------------------
|
onSelectedContactsChanged: Qt.callLater(function(){mainItem.selectedParticipants = selectedContacts})
|
||||||
sourceComponent: ContactListView{
|
searchBarText: searchBar.text
|
||||||
id: contactList
|
onContactAddedToSelection: (address) => {
|
||||||
Layout.fillWidth: true
|
contactList.addContactToSelection(address)
|
||||||
Layout.fillHeight: true
|
|
||||||
itemsRightMargin: 28 * DefaultStyle.dp
|
|
||||||
multiSelectionEnabled: true
|
|
||||||
showContactMenu: false
|
|
||||||
confInfoGui: mainItem.conferenceInfoGui
|
|
||||||
selectedContacts: mainItem.selectedParticipants
|
|
||||||
onSelectedContactsChanged: Qt.callLater(function(){mainItem.selectedParticipants = selectedContacts})
|
|
||||||
searchBarText: searchBar.text
|
|
||||||
onContactAddedToSelection: (address) => {
|
|
||||||
contactList.addContactToSelection(address)
|
|
||||||
}
|
|
||||||
onContactRemovedFromSelection: (address) => contactList.removeSelectedContactByAddress(address)
|
|
||||||
}
|
}
|
||||||
|
onContactRemovedFromSelection: (address) => contactList.removeSelectedContactByAddress(address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,8 +172,8 @@ Item {
|
||||||
if (text.length != 0) listPopup.open()
|
if (text.length != 0) listPopup.open()
|
||||||
else listPopup.close()
|
else listPopup.close()
|
||||||
}
|
}
|
||||||
KeyNavigation.down: contactLoader.item?.count > 0 || !contactLoader.item?.footerItem? contactLoader.item : contactLoader.item?.footerItem
|
KeyNavigation.down: contactList //contactLoader.item?.count > 0 || !contactLoader.item?.footerItem? contactLoader.item : contactLoader.item?.footerItem
|
||||||
KeyNavigation.up: contactLoader.item?.footerItem ? contactLoader.item?.footerItem : contactLoader.item
|
KeyNavigation.up: contactList//contactLoader.item?.footerItem ? contactLoader.item?.footerItem : contactLoader.item
|
||||||
|
|
||||||
component MagicSearchButton: Button {
|
component MagicSearchButton: Button {
|
||||||
id: button
|
id: button
|
||||||
|
|
@ -197,8 +197,8 @@ Item {
|
||||||
id: listPopup
|
id: listPopup
|
||||||
width: magicSearchBar.width
|
width: magicSearchBar.width
|
||||||
property int maxHeight: 400 * DefaultStyle.dp
|
property int maxHeight: 400 * DefaultStyle.dp
|
||||||
property bool displayScrollbar: contactLoader.item?.contentHeight + topPadding + bottomPadding> maxHeight
|
property bool displayScrollbar: contactList.contentHeight + topPadding + bottomPadding> maxHeight
|
||||||
height: Math.min(contactLoader.item?.contentHeight + topPadding + bottomPadding, maxHeight)
|
height: Math.min(contactList.contentHeight + topPadding + bottomPadding, maxHeight)
|
||||||
y: magicSearchBar.height
|
y: magicSearchBar.height
|
||||||
// closePolicy: Popup.NoAutoClose
|
// closePolicy: Popup.NoAutoClose
|
||||||
topPadding: 20 * DefaultStyle.dp
|
topPadding: 20 * DefaultStyle.dp
|
||||||
|
|
@ -214,7 +214,7 @@ Item {
|
||||||
color: DefaultStyle.grey_0
|
color: DefaultStyle.grey_0
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
border.color: DefaultStyle.main1_500_main
|
border.color: DefaultStyle.main1_500_main
|
||||||
border.width: contactLoader.item?.activeFocus ? 2 : 0
|
border.width: contactList.activeFocus ? 2 : 0
|
||||||
|
|
||||||
}
|
}
|
||||||
MultiEffect {
|
MultiEffect {
|
||||||
|
|
@ -238,23 +238,10 @@ Item {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
contentItem: Loader{
|
contentItem: AllContactListView {
|
||||||
// This is a hack for an incomprehensible behavior on sections title where they doesn't match with their delegate and can be unordered after resetting models.
|
|
||||||
id: contactLoader
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
property bool deactivate: false
|
|
||||||
active: !deactivate && magicSearchBar.text != ''
|
|
||||||
property string t: magicSearchBar.text
|
|
||||||
onTChanged: {
|
|
||||||
contactLoader.deactivate = true
|
|
||||||
Qt.callLater(function(){contactLoader.deactivate=false})
|
|
||||||
}
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
sourceComponent: ContactListView {
|
|
||||||
id: contactList
|
id: contactList
|
||||||
visible: magicSearchBar.text.length != 0
|
visible: magicSearchBar.text.length != 0
|
||||||
Layout.preferredHeight: item?.contentHeight
|
Layout.preferredHeight: contentHeight
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
itemsRightMargin: 5 * DefaultStyle.dp //(Actions have already 10 of margin)
|
itemsRightMargin: 5 * DefaultStyle.dp //(Actions have already 10 of margin)
|
||||||
showInitials: false
|
showInitials: false
|
||||||
|
|
@ -263,6 +250,7 @@ Item {
|
||||||
showFavorites: false
|
showFavorites: false
|
||||||
selectionEnabled: false
|
selectionEnabled: false
|
||||||
showDefaultAddress: true
|
showDefaultAddress: true
|
||||||
|
searchOnEmpty: false
|
||||||
|
|
||||||
sectionsPixelSize: 13 * DefaultStyle.dp
|
sectionsPixelSize: 13 * DefaultStyle.dp
|
||||||
sectionsWeight: 700 * DefaultStyle.dp
|
sectionsWeight: 700 * DefaultStyle.dp
|
||||||
|
|
@ -270,24 +258,7 @@ Item {
|
||||||
|
|
||||||
Control.ScrollBar.vertical: scrollbar
|
Control.ScrollBar.vertical: scrollbar
|
||||||
searchBarText: magicSearchBar.text
|
searchBarText: magicSearchBar.text
|
||||||
|
|
||||||
Keys.onPressed: (event) => {
|
|
||||||
if(event.key == Qt.Key_Down){
|
|
||||||
if(contactList.currentIndex == contactList.count -1) {
|
|
||||||
contactList.currentIndex = -1
|
|
||||||
contactList.footerItem.forceActiveFocus()
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
} else if(event.key == Qt.Key_Up){
|
|
||||||
if(contactList.currentIndex <= 0) {
|
|
||||||
contactList.currentIndex = -1
|
|
||||||
contactList.footerItem.forceActiveFocus()
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
|
|
||||||
|
|
@ -239,22 +239,21 @@ AbstractMainPage {
|
||||||
Qt.callLater(function(){contactLoader.active=true})
|
Qt.callLater(function(){contactLoader.active=true})
|
||||||
}
|
}
|
||||||
//-------------------------------------------------------------
|
//-------------------------------------------------------------
|
||||||
sourceComponent: ContactListView{
|
sourceComponent: AllContactListView{
|
||||||
id: contactList
|
id: contactList
|
||||||
searchBarText: searchBar.text
|
searchBarText: searchBar.text
|
||||||
hideSuggestions: true
|
hideSuggestions: true
|
||||||
showDefaultAddress: false
|
showDefaultAddress: false
|
||||||
sourceFlags: LinphoneEnums.MagicSearchSource.Friends | LinphoneEnums.MagicSearchSource.FavoriteFriends | LinphoneEnums.MagicSearchSource.LdapServers
|
sourceFlags: LinphoneEnums.MagicSearchSource.Friends | LinphoneEnums.MagicSearchSource.FavoriteFriends | LinphoneEnums.MagicSearchSource.LdapServers
|
||||||
|
onHighlightedContactChanged: mainItem.selectedContact = highlightedContact
|
||||||
onSelectedContactChanged: {
|
|
||||||
mainItem.selectedContact = selectedContact
|
|
||||||
}
|
|
||||||
onContactDeletionRequested: (contact) => {
|
onContactDeletionRequested: (contact) => {
|
||||||
mainItem.deleteContact(contact)
|
mainItem.deleteContact(contact)
|
||||||
}
|
}
|
||||||
onCountChanged: {
|
onLoadingChanged: {
|
||||||
if (initialFriendToDisplay.length !== 0) {
|
if(!loading && initialFriendToDisplay.length !== 0) {
|
||||||
if (selectContact(initialFriendToDisplay) != -1) initialFriendToDisplay = ""
|
Qt.callLater(function(){
|
||||||
|
if (selectContact(initialFriendToDisplay) != -1) initialFriendToDisplay = ""
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
external/linphone-sdk
vendored
2
external/linphone-sdk
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 08d52ccdc63c859f14ffa160b954d1f954a5a272
|
Subproject commit 4e2af5b435cb7fd6aadc9cd2b7eb45ba547cf5e8
|
||||||
Loading…
Reference in a new issue