mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 11:28:07 +00:00
fix slow loading when many friends
This commit is contained in:
parent
b4b573a027
commit
c1013baac5
14 changed files with 384 additions and 384 deletions
|
|
@ -59,7 +59,8 @@ void MagicSearchList::setSelf(QSharedPointer<MagicSearchList> me) {
|
|||
auto itemCore = item.objectCast<FriendCore>();
|
||||
return itemCore->getDefaultAddress().length() > 0 &&
|
||||
itemCore->getDefaultAddress() == friendCore->getDefaultAddress() ||
|
||||
itemCore->getFriendModel()->getFriend() == friendCore->getFriendModel()->getFriend();
|
||||
itemCore->getFriendModel() && friendCore->getFriendModel() &&
|
||||
itemCore->getFriendModel()->getFriend() == friendCore->getFriendModel()->getFriend();
|
||||
});
|
||||
if (haveContact == mList.end()) {
|
||||
connect(friendCore.get(), &FriendCore::removed, this, qOverload<QObject *>(&MagicSearchList::remove));
|
||||
|
|
@ -117,8 +118,9 @@ void MagicSearchList::setSelf(QSharedPointer<MagicSearchList> me) {
|
|||
address->asString())); // linphone Friend object remove specific address.
|
||||
contacts->append(contact);
|
||||
} else if (!it->getPhoneNumber().empty()) {
|
||||
auto phoneNumber = it->getPhoneNumber();
|
||||
linphoneFriend = CoreModel::getInstance()->getCore()->createFriend();
|
||||
linphoneFriend->setAddress(address);
|
||||
linphoneFriend->addPhoneNumber(phoneNumber);
|
||||
contact = FriendCore::create(linphoneFriend, isStored, it->getSourceFlags());
|
||||
contact->setGivenName(Utils::coreStringToAppString(it->getPhoneNumber()));
|
||||
contact->appendPhoneNumber(tr("Phone"), Utils::coreStringToAppString(it->getPhoneNumber()));
|
||||
|
|
@ -128,6 +130,7 @@ void MagicSearchList::setSelf(QSharedPointer<MagicSearchList> me) {
|
|||
mModelConnection->invokeToCore([this, contacts]() {
|
||||
setResults(*contacts);
|
||||
delete contacts;
|
||||
emit resultsProcessed();
|
||||
});
|
||||
});
|
||||
qDebug() << log().arg("Initialized");
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ signals:
|
|||
void friendCreated(int index, FriendGui *data);
|
||||
void friendStarredChanged();
|
||||
|
||||
void resultsProcessed();
|
||||
|
||||
void initialized();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -25,11 +25,13 @@
|
|||
#include "core/friend/FriendCore.hpp"
|
||||
|
||||
MagicSearchProxy::MagicSearchProxy(QObject *parent) : LimitProxy(parent) {
|
||||
setList(MagicSearchList::create());
|
||||
auto magicSearchList = MagicSearchList::create();
|
||||
setList(magicSearchList);
|
||||
connect(this, &MagicSearchProxy::forceUpdate, [this] {
|
||||
if (mList) emit mList->lSearch(mSearchText, getSourceFlags(), getAggregationFlag(), getMaxResults());
|
||||
});
|
||||
connect(App::getInstance(), &App::currentDateChanged, this, &MagicSearchProxy::forceUpdate);
|
||||
connect(magicSearchList.get(), &MagicSearchList::resultsProcessed, this, &MagicSearchProxy::resultsProcessed);
|
||||
}
|
||||
|
||||
MagicSearchProxy::~MagicSearchProxy() {
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ signals:
|
|||
void parentProxyChanged();
|
||||
void hideListProxyChanged();
|
||||
void initialized();
|
||||
void resultsProcessed();
|
||||
|
||||
protected:
|
||||
MagicSearchProxy *mParentProxy = nullptr;
|
||||
|
|
|
|||
|
|
@ -81,31 +81,23 @@ void MagicSearchModel::onSearchResultsReceived(const std::shared_ptr<linphone::M
|
|||
auto appFriends = ToolModel::getAppFriendList();
|
||||
auto ldapFriends = ToolModel::getLdapFriendList();
|
||||
std::list<std::shared_ptr<linphone::SearchResult>> finalResults;
|
||||
emit searchResultsReceived(results);
|
||||
for (auto result : results) {
|
||||
auto f = result->getFriend();
|
||||
auto fList = f ? f->getFriendList() : nullptr;
|
||||
|
||||
qDebug() << log().arg("") << (f ? f->getName().c_str() : "NoFriend") << ", "
|
||||
<< (result->getAddress() ? result->getAddress()->asString().c_str() : "NoAddr") << " / "
|
||||
<< (fList ? fList->getDisplayName().c_str() : "NoList") << result->getSourceFlags() << " / "
|
||||
<< (f ? f.get() : nullptr);
|
||||
// qDebug() << log().arg("") << (f ? f->getName().c_str() : "NoFriend") << ", "
|
||||
// << (result->getAddress() ? result->getAddress()->asString().c_str() : "NoAddr") << " / "
|
||||
// << (fList ? fList->getDisplayName().c_str() : "NoList") << result->getSourceFlags() << " / "
|
||||
// << (f ? f.get() : nullptr);
|
||||
|
||||
bool isLdap = (result->getSourceFlags() & (int)linphone::MagicSearch::Source::LdapServers) != 0;
|
||||
// Do not add it into ldap_friends if it already exists in app_friends.
|
||||
if (isLdap && f && (!fList || fList->getDisplayName() != "app_friends") &&
|
||||
!ToolModel::friendIsInFriendList(appFriends, f)) { // Double check because of SDK merging that lead to
|
||||
// use a ldap result as of app_friends/ldap_friends.
|
||||
updateFriendListWithFriend(f, ToolModel::getLdapFriendList());
|
||||
if (isLdap && f && (!fList || fList->getDisplayName() != "app_friends")) { // Double check because of SDK merging that lead to
|
||||
// use a ldap result as of app_friends/ldap_friends.
|
||||
updateFriendListWithFriend(f, ldapFriends);
|
||||
}
|
||||
|
||||
auto resultIt =
|
||||
std::find_if(finalResults.begin(), finalResults.end(), [result](std::shared_ptr<linphone::SearchResult> r) {
|
||||
return r->getAddress() && r->getAddress()->weakEqual(result->getAddress());
|
||||
});
|
||||
if (resultIt == finalResults.end()) finalResults.push_back(result);
|
||||
else if (fList && fList->getDisplayName() == "app_friends") *resultIt = result; // replace if local friend
|
||||
}
|
||||
emit searchResultsReceived(finalResults);
|
||||
}
|
||||
|
||||
void MagicSearchModel::onMoreResultsAvailable(const std::shared_ptr<linphone::MagicSearch> &magicSearch,
|
||||
|
|
|
|||
|
|
@ -296,13 +296,12 @@ std::shared_ptr<linphone::FriendList> ToolModel::getLdapFriendList() {
|
|||
}
|
||||
|
||||
bool ToolModel::friendIsInFriendList(const std::shared_ptr<linphone::FriendList> &friendList,
|
||||
const std::shared_ptr<linphone::Friend> &f) {
|
||||
for (auto contact : friendList->getFriends()) {
|
||||
if (f == contact) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
const std::shared_ptr<linphone::Friend> &f) {
|
||||
auto friends = friendList->getFriends();
|
||||
auto it = std::find_if(friends.begin(), friends.end(), [f] (std::shared_ptr<linphone::Friend> linFriend) {
|
||||
return linFriend == f;
|
||||
});
|
||||
return (it != friends.end());
|
||||
}
|
||||
|
||||
// Load downloaded codecs like OpenH264 (needs to be after core is created and has loaded its plugins, as
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
|||
view/Control/Button/CheckBox.qml
|
||||
view/Control/Button/ComboBox.qml
|
||||
view/Control/Button/HelpIconLabelButton.qml
|
||||
view/Control/Button/IconButton.qml
|
||||
view/Control/Button/IconLabelButton.qml
|
||||
view/Control/Button/BigButton.qml
|
||||
view/Control/Button/IconButton.qml
|
||||
view/Control/Button/IconLabelButton.qml
|
||||
view/Control/Button/BigButton.qml
|
||||
view/Control/Button/RoundButton.qml
|
||||
view/Control/Button/MediumButton.qml
|
||||
view/Control/Button/SmallButton.qml
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@ import Linphone
|
|||
Control.ScrollBar {
|
||||
id: mainItem
|
||||
padding: 0
|
||||
property color color: DefaultStyle.grey_850
|
||||
contentItem: Rectangle {
|
||||
implicitWidth: 6 * DefaultStyle.dp
|
||||
radius: 32 * DefaultStyle.dp
|
||||
color: DefaultStyle.grey_850
|
||||
color: mainItem.color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,328 +8,340 @@ import ConstantsCpp 1.0
|
|||
import SettingsCpp
|
||||
import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils
|
||||
|
||||
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
|
||||
Flickable {
|
||||
id: mainItem
|
||||
|
||||
// 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 + suggestionsList.count + favoritesList.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
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
function resetSelections(){
|
||||
mainItem.highlightedContact = null
|
||||
favoritesList.currentIndex = -1
|
||||
contactsList.currentIndex = -1
|
||||
suggestionsList.currentIndex = -1
|
||||
}
|
||||
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
|
||||
|
||||
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){
|
||||
Utils.updatePosition(mainItem, list)
|
||||
}
|
||||
|
||||
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 && contactList.expanded ) || mainItem.hideSuggestions) contactsProxy.displayMore()
|
||||
else suggestionsProxy.displayMore()
|
||||
}
|
||||
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)
|
||||
else if(contactsList.activeFocus) newItem = findNextList(contactsList, 0, direction)
|
||||
else if(favoritesList.activeFocus) newItem = findNextList(favoritesList, 0, direction)
|
||||
else newItem = findNextList(suggestionsList, 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.resetSelections()
|
||||
mainItem.resultsReceived()
|
||||
}
|
||||
|
||||
onInitialized: {
|
||||
if(mainItem.searchOnEmpty || searchText != '' ) {
|
||||
mainItem.loading = true
|
||||
forceUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property bool displayNameCapitalization: true // Capitalize display name.
|
||||
|
||||
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
|
||||
spacing: 20 * DefaultStyle.dp
|
||||
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
|
||||
visible: contentHeight > 0
|
||||
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
|
||||
visible: contentHeight > 0
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: implicitHeight
|
||||
Layout.topMargin: favoritesList.height > 0 ? 4 * DefaultStyle.dp : 0
|
||||
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 | MagicSearchProxy.FilteringTypes.CardDAV: 0)
|
||||
initialDisplayItems: Math.max(20, 2 * mainItem.height / (63 * DefaultStyle.dp))
|
||||
displayItemsStep: 3 * initialDisplayItems / 2
|
||||
onLocalFriendCreated: (index) => {
|
||||
contactsList.selectIndex(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
ContactListView{
|
||||
id: suggestionsList
|
||||
visible: contentHeight > 0
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: implicitHeight
|
||||
Layout.topMargin: contactsList.height + favoritesList.height > 0 ? 4 * DefaultStyle.dp : 0
|
||||
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: contactsProxy.haveMore && contactsList.expanded ? 0 : Math.max(20, 2 * mainItem.height / (63 * DefaultStyle.dp))
|
||||
onInitialDisplayItemsChanged: maxDisplayItems = initialDisplayItems
|
||||
displayItemsStep: 3 * initialDisplayItems / 2
|
||||
onModelReset: maxDisplayItems = initialDisplayItems
|
||||
}
|
||||
}
|
||||
}
|
||||
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 busyIndicatorSize: 40 * DefaultStyle.dp
|
||||
|
||||
property int itemsRightMargin: 39 * DefaultStyle.dp
|
||||
property int count: contactsList.count + suggestionsList.count + favoritesList.count
|
||||
|
||||
contentHeight: contentsLayout.height
|
||||
rightMargin: itemsRightMargin
|
||||
|
||||
signal contactStarredChanged()
|
||||
signal contactDeletionRequested(FriendGui contact)
|
||||
signal contactAddedToSelection(string address)
|
||||
signal contactRemovedFromSelection(string address)
|
||||
signal contactSelected(FriendGui contact)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
function resetSelections(){
|
||||
mainItem.highlightedContact = null
|
||||
favoritesList.currentIndex = -1
|
||||
contactsList.currentIndex = -1
|
||||
suggestionsList.currentIndex = -1
|
||||
}
|
||||
|
||||
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){
|
||||
Utils.updatePosition(mainItem, list)
|
||||
}
|
||||
|
||||
onHighlightedContactChanged:{
|
||||
favoritesList.highlightedContact = highlightedContact
|
||||
contactsList.highlightedContact = highlightedContact
|
||||
suggestionsList.highlightedContact = highlightedContact
|
||||
}
|
||||
|
||||
onSearchBarTextChanged: {
|
||||
if(!pauseSearch && (mainItem.searchOnEmpty || searchBarText != '')) {
|
||||
console.log("change search text")
|
||||
searchText = searchBarText.length === 0 ? "*" : searchBarText
|
||||
}
|
||||
}
|
||||
onPauseSearchChanged: {
|
||||
if(!pauseSearch && (mainItem.searchOnEmpty || searchBarText != '')){
|
||||
searchText = searchBarText.length === 0 ? "*" : searchBarText
|
||||
}
|
||||
}
|
||||
onSearchTextChanged: {
|
||||
console.log("search texte changed, loading...")
|
||||
loading = true
|
||||
}
|
||||
|
||||
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)
|
||||
else if(contactsList.activeFocus) newItem = findNextList(contactsList, 0, direction)
|
||||
else if(favoritesList.activeFocus) newItem = findNextList(favoritesList, 0, direction)
|
||||
else newItem = findNextList(suggestionsList, 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.resetSelections()
|
||||
|
||||
}
|
||||
onResultsProcessed: {
|
||||
console.log("result processed list view")
|
||||
mainItem.loading = false
|
||||
mainItem.contentY = 0
|
||||
}
|
||||
|
||||
onInitialized: {
|
||||
if(mainItem.searchOnEmpty || searchText != '' ) {
|
||||
mainItem.loading = true
|
||||
forceUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onAtYEndChanged: if(atYEnd) {
|
||||
if( (contactsProxy.haveMore && contactList.expanded ) || mainItem.hideSuggestions) contactsProxy.displayMore()
|
||||
else suggestionsProxy.displayMore()
|
||||
}
|
||||
Behavior on contentY{
|
||||
NumberAnimation {
|
||||
duration: 500
|
||||
easing.type: Easing.OutExpo
|
||||
}
|
||||
}
|
||||
|
||||
Control.ScrollBar.vertical: ScrollBar {
|
||||
id: scrollbar
|
||||
z: 1
|
||||
topPadding: 24 * DefaultStyle.dp // Avoid to be on top of collapse button
|
||||
active: true
|
||||
interactive: true
|
||||
visible: mainItem.contentHeight > mainItem.height
|
||||
policy: Control.ScrollBar.AsNeeded
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: contentsLayout
|
||||
width: mainItem.width
|
||||
spacing: 0//20 * DefaultStyle.dp
|
||||
|
||||
BusyIndicator {
|
||||
id: busyIndicator
|
||||
visible: mainItem.loading
|
||||
width: mainItem.busyIndicatorSize
|
||||
height: mainItem.busyIndicatorSize
|
||||
Layout.preferredWidth: mainItem.busyIndicatorSize
|
||||
Layout.preferredHeight: mainItem.busyIndicatorSize
|
||||
Layout.alignment: Qt.AlignCenter | Qt.AlignVCenter
|
||||
}
|
||||
|
||||
ContactListView{
|
||||
id: favoritesList
|
||||
visible: contentHeight > 0
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: implicitHeight
|
||||
sectionsWeight: mainItem.sectionsWeight
|
||||
sectionsPixelSize: mainItem.sectionsPixelSize
|
||||
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')
|
||||
itemsRightMargin: mainItem.itemsRightMargin
|
||||
|
||||
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
|
||||
visible: contentHeight > 0
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: implicitHeight
|
||||
Layout.topMargin: favoritesList.height > 0 ? 4 * DefaultStyle.dp : 0
|
||||
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
|
||||
itemsRightMargin: mainItem.itemsRightMargin
|
||||
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 | MagicSearchProxy.FilteringTypes.CardDAV: 0)
|
||||
initialDisplayItems: Math.max(20, 2 * mainItem.height / (63 * DefaultStyle.dp))
|
||||
displayItemsStep: 3 * initialDisplayItems / 2
|
||||
onLocalFriendCreated: (index) => {
|
||||
contactsList.selectIndex(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
ContactListView{
|
||||
id: suggestionsList
|
||||
visible: contentHeight > 0
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: implicitHeight
|
||||
Layout.topMargin: contactsList.height + favoritesList.height > 0 ? 4 * DefaultStyle.dp : 0
|
||||
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')
|
||||
itemsRightMargin: mainItem.itemsRightMargin
|
||||
|
||||
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: contactsProxy.haveMore && contactsList.expanded ? 0 : Math.max(20, 2 * mainItem.height / (63 * DefaultStyle.dp))
|
||||
onInitialDisplayItemsChanged: maxDisplayItems = initialDisplayItems
|
||||
displayItemsStep: 3 * initialDisplayItems / 2
|
||||
onModelReset: maxDisplayItems = initialDisplayItems
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ FocusScope {
|
|||
id: actionButtons
|
||||
visible: mainItem.showActions
|
||||
spacing: visible ? 10 * DefaultStyle.dp : 0
|
||||
Button {
|
||||
IconButton {
|
||||
id: callButton
|
||||
Layout.preferredWidth: 45 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 45 * DefaultStyle.dp
|
||||
|
|
@ -128,7 +128,7 @@ FocusScope {
|
|||
KeyNavigation.left: chatButton
|
||||
KeyNavigation.right: videoCallButton
|
||||
}
|
||||
Button {
|
||||
IconButton {
|
||||
id: videoCallButton
|
||||
Layout.preferredWidth: 45 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 45 * DefaultStyle.dp
|
||||
|
|
@ -142,7 +142,7 @@ FocusScope {
|
|||
KeyNavigation.left: callButton
|
||||
KeyNavigation.right: chatButton
|
||||
}
|
||||
Button {
|
||||
IconButton {
|
||||
id: chatButton
|
||||
visible: actionButtons.visible && !SettingsCpp.disableChatFeature
|
||||
Layout.preferredWidth: 45 * DefaultStyle.dp
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ ListView {
|
|||
property bool expanded: true
|
||||
property int headerHeight: headerItem?.height
|
||||
|
||||
signal resultsReceived()
|
||||
signal contactDeletionRequested(FriendGui contact)
|
||||
signal contactSelected(FriendGui contact) // Click/Space/Enter
|
||||
signal addContactToSelection(var address)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ Loader {
|
|||
|
||||
MultiEffect {
|
||||
id: effect2
|
||||
enabled: effectEnabled
|
||||
visible: mainItem.useColor
|
||||
property bool effectEnabled: mainItem.useColor
|
||||
anchors.fill: effect
|
||||
|
|
|
|||
|
|
@ -191,21 +191,22 @@ Item {
|
|||
id: listPopup
|
||||
width: magicSearchBar.width
|
||||
property int maxHeight: 400 * DefaultStyle.dp
|
||||
property bool displayScrollbar: contactList.contentHeight + topPadding + bottomPadding> maxHeight
|
||||
height: contactList.haveContacts ? Math.min(contactList.contentHeight + topPadding + bottomPadding, maxHeight) : 0
|
||||
property bool displayScrollbar: contactList.height > maxHeight
|
||||
height: Math.min(contactList.contentHeight, maxHeight) + topPadding + bottomPadding
|
||||
y: magicSearchBar.height
|
||||
// closePolicy: Popup.NoAutoClose
|
||||
topPadding: contactList.haveContacts ? 20 * DefaultStyle.dp : 0
|
||||
bottomPadding: contactList.haveContacts ? 20 * DefaultStyle.dp : 0
|
||||
rightPadding: 10 * DefaultStyle.dp
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
topPadding: 20 * DefaultStyle.dp
|
||||
bottomPadding: contactList.haveContacts ? 20 * DefaultStyle.dp : 10 * DefaultStyle.dp
|
||||
rightPadding: 8 * DefaultStyle.dp
|
||||
leftPadding: 20 * DefaultStyle.dp
|
||||
|
||||
visible: magicSearchBar.text.length != 0
|
||||
|
||||
background: Item {
|
||||
anchors.fill: parent
|
||||
Rectangle {
|
||||
id: popupBg
|
||||
radius: 16 * DefaultStyle.dp
|
||||
color: DefaultStyle.grey_0
|
||||
color: DefaultStyle.grey_0
|
||||
anchors.fill: parent
|
||||
border.color: DefaultStyle.main1_500_main
|
||||
border.width: contactList.activeFocus ? 2 : 0
|
||||
|
|
@ -218,25 +219,12 @@ Item {
|
|||
shadowBlur: 0.1
|
||||
shadowColor: DefaultStyle.grey_1000
|
||||
shadowOpacity: 0.1
|
||||
}
|
||||
ScrollBar {
|
||||
id: scrollbar
|
||||
Component.onCompleted: x = -10 * DefaultStyle.dp
|
||||
policy: Control.ScrollBar.AsNeeded// Don't work as expected
|
||||
visible: listPopup.displayScrollbar
|
||||
interactive: true
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.margins: 10 * DefaultStyle.dp
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
contentItem: AllContactListView {
|
||||
id: contactList
|
||||
visible: !loading && magicSearchBar.text.length != 0
|
||||
Layout.preferredHeight: visible ? contentHeight : 0
|
||||
Layout.fillWidth: true
|
||||
|
||||
contentItem: AllContactListView {
|
||||
id: contactList
|
||||
width: listPopup.width - listPopup.leftPadding - listPopup.rightPadding
|
||||
itemsRightMargin: 5 * DefaultStyle.dp //(Actions have already 10 of margin)
|
||||
showInitials: false
|
||||
showContactMenu: false
|
||||
|
|
@ -250,8 +238,7 @@ Item {
|
|||
sectionsWeight: 700 * DefaultStyle.dp
|
||||
sectionsSpacing: 5 * DefaultStyle.dp
|
||||
|
||||
Control.ScrollBar.vertical: scrollbar
|
||||
searchBarText: magicSearchBar.text
|
||||
searchBarText: magicSearchBar.text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ AbstractMainPage {
|
|||
ColumnLayout {
|
||||
id: content
|
||||
spacing: 15 * DefaultStyle.dp
|
||||
Layout.leftMargin: 45 * DefaultStyle.dp
|
||||
Text {
|
||||
visible: !contactList.loading && !contactList.haveContacts
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
|
@ -241,7 +242,7 @@ AbstractMainPage {
|
|||
id: contactList
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: 45 * DefaultStyle.dp
|
||||
Layout.rightMargin: 8 * DefaultStyle.dp
|
||||
searchBarText: searchBar.text
|
||||
hideSuggestions: true
|
||||
showDefaultAddress: false
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue