contact list
generic VariantList
FriendModel resetAddresses
check null default account
address list update on save
generic item for white background lists
ui
fix set photo friend
protect friendmodel setters
remove main splitview to stick to the mock-up (keeping it commented cause it may be useful to be able to resize the panels)
default image avatar
fix crash when address not set
fix ui in call
Really fix call variantobject destroying himself before call started
fix: display suggestions
fix list view current item always reset cause updated every time contact history list changed
fix blinking call log list view on content changed
fix popup button popup y when exceed window
delete contact confirmation popup
fix popup call contact list
don't show popup if only one address possible
set/remove default address if append/remove from address list
This commit is contained in:
Gaelle Braud 2024-02-05 11:12:19 +01:00
parent 64c430cd38
commit a2154a6c7b
18 changed files with 194 additions and 147 deletions

View file

@ -301,12 +301,16 @@ void FriendCore::setAddressAt(int index, const QString &label, const QString &ad
} }
void FriendCore::removeAddress(int index) { void FriendCore::removeAddress(int index) {
if (index != -1) mAddressList.remove(index); if (index < 0 && index >= mAddressList.size()) return;
auto map = mAddressList[index].toMap();
if (map["address"].toString() == mDefaultAddress) mDefaultAddress.clear();
mAddressList.remove(index);
emit addressChanged(); emit addressChanged();
} }
void FriendCore::appendAddress(const QString &addr) { void FriendCore::appendAddress(const QString &addr) {
mAddressList.append(createFriendAddressVariant(addressLabel, addr)); mAddressList.append(createFriendAddressVariant(addressLabel, addr));
if (mDefaultAddress.isEmpty()) mDefaultAddress = addr;
emit addressChanged(); emit addressChanged();
} }
@ -324,6 +328,9 @@ QString FriendCore::getDefaultAddress() const {
} }
void FriendCore::setDefaultAddress(const QString &address) { void FriendCore::setDefaultAddress(const QString &address) {
auto it = std::find_if(mAddressList.begin(), mAddressList.end(),
[address](const QVariant &a) { return a.toMap()["address"].toString() == address; });
if (it == mAddressList.end()) appendAddress(address);
if (mDefaultAddress != address) { if (mDefaultAddress != address) {
mDefaultAddress = address; mDefaultAddress = address;
emit defaultAddressChanged(); emit defaultAddressChanged();

View file

@ -44,7 +44,7 @@ class FriendCore;
class FriendCore : public QObject, public AbstractObject { class FriendCore : public QObject, public AbstractObject {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QList<QVariant> allAdresses READ getAllAddresses NOTIFY allAddressesChanged) Q_PROPERTY(QList<QVariant> allAddresses READ getAllAddresses NOTIFY allAddressesChanged)
Q_PROPERTY(QList<QVariant> phoneNumbers READ getPhoneNumbers NOTIFY phoneNumberChanged) Q_PROPERTY(QList<QVariant> phoneNumbers READ getPhoneNumbers NOTIFY phoneNumberChanged)
Q_PROPERTY(QList<QVariant> addresses READ getAddresses NOTIFY addressChanged) Q_PROPERTY(QList<QVariant> addresses READ getAddresses NOTIFY addressChanged)
Q_PROPERTY(QString givenName READ getGivenName WRITE setGivenName NOTIFY givenNameChanged) Q_PROPERTY(QString givenName READ getGivenName WRITE setGivenName NOTIFY givenNameChanged)
@ -92,14 +92,12 @@ public:
Q_INVOKABLE void appendPhoneNumber(const QString &label, const QString &number); Q_INVOKABLE void appendPhoneNumber(const QString &label, const QString &number);
Q_INVOKABLE void removePhoneNumber(int index); Q_INVOKABLE void removePhoneNumber(int index);
Q_INVOKABLE void setPhoneNumberAt(int index, const QString &label, const QString &phoneNumber); Q_INVOKABLE void setPhoneNumberAt(int index, const QString &label, const QString &phoneNumber);
void resetPhoneNumbers(QList<QVariant> newList);
QList<QVariant> getAddresses() const; QList<QVariant> getAddresses() const;
QVariant getAddressAt(int index) const; QVariant getAddressAt(int index) const;
Q_INVOKABLE void appendAddress(const QString &addr); Q_INVOKABLE void appendAddress(const QString &addr);
Q_INVOKABLE void removeAddress(int index); Q_INVOKABLE void removeAddress(int index);
Q_INVOKABLE void setAddressAt(int index, const QString &label, const QString &address); Q_INVOKABLE void setAddressAt(int index, const QString &label, const QString &address);
void resetAddresses(QList<QVariant> newList);
void setDefaultAddress(const QString &address); void setDefaultAddress(const QString &address);
QString getDefaultAddress() const; QString getDefaultAddress() const;
@ -125,6 +123,10 @@ public:
Q_INVOKABLE void save(); Q_INVOKABLE void save();
Q_INVOKABLE void undo(); Q_INVOKABLE void undo();
protected:
void resetPhoneNumbers(QList<QVariant> newList);
void resetAddresses(QList<QVariant> newList);
signals: signals:
void contactUpdated(); void contactUpdated();
void displayNameChanged(); void displayNameChanged();

View file

@ -61,7 +61,7 @@ void LoginPage::setErrorMessage(const QString &error) {
void LoginPage::login(const QString &username, const QString &password) { void LoginPage::login(const QString &username, const QString &password) {
App::postModelAsync([=]() { App::postModelAsync([=]() {
QString *error = new QString(tr("Le couple identifiant mot de passe ne correspont pas")); QString *error = new QString(tr("Le couple identifiant mot de passe ne correspond pas"));
// Create on Model thread. // Create on Model thread.
AccountManager *accountManager = new AccountManager(); AccountManager *accountManager = new AccountManager();
connect(accountManager, &AccountManager::registrationStateChanged, this, connect(accountManager, &AccountManager::registrationStateChanged, this,

View file

@ -73,7 +73,8 @@ void MagicSearchList::setSelf(QSharedPointer<MagicSearchList> me) {
mModelConnection->invokeToCore([this, flag]() { setAggregationFlag(flag); }); mModelConnection->invokeToCore([this, flag]() { setAggregationFlag(flag); });
}); });
mModelConnection->makeConnectToModel(&MagicSearchModel::searchResultsReceived, mModelConnection->makeConnectToModel(
&MagicSearchModel::searchResultsReceived,
[this](const std::list<std::shared_ptr<linphone::SearchResult>> &results) { [this](const std::list<std::shared_ptr<linphone::SearchResult>> &results) {
auto *contacts = new QList<QSharedPointer<FriendCore>>(); auto *contacts = new QList<QSharedPointer<FriendCore>>();
for (auto it : results) { for (auto it : results) {
@ -81,6 +82,16 @@ void MagicSearchList::setSelf(QSharedPointer<MagicSearchList> me) {
if (it->getFriend()) { if (it->getFriend()) {
contact = FriendCore::create(it->getFriend()); contact = FriendCore::create(it->getFriend());
contacts->append(contact); contacts->append(contact);
} else if (auto address = it->getAddress()) {
contact = FriendCore::create(nullptr);
contact->setGivenName(Utils::coreStringToAppString(address->asStringUriOnly()));
contact->appendAddress(Utils::coreStringToAppString(address->asStringUriOnly()));
contacts->append(contact);
} else if (!it->getPhoneNumber().empty()) {
contact = FriendCore::create(it->getFriend());
contact->setGivenName(Utils::coreStringToAppString(it->getPhoneNumber()));
contact->appendPhoneNumber(tr("Phone"), Utils::coreStringToAppString(it->getPhoneNumber()));
contacts->append(contact);
} }
} }
mModelConnection->invokeToCore([this, contacts]() { mModelConnection->invokeToCore([this, contacts]() {

View file

@ -38,13 +38,11 @@ VariantObject::VariantObject(QVariant defaultValue, QObject *parent) {
mConnection->makeConnectToCore(&SafeObject::setValue, [this](QVariant value) { mConnection->makeConnectToCore(&SafeObject::setValue, [this](QVariant value) {
mConnection->invokeToModel([this, value]() { mConnection->invokeToModel([this, value]() {
// TODO : fix this properly
if (mModelObject) mModelObject->onSetValue(value); if (mModelObject) mModelObject->onSetValue(value);
}); });
}); });
mConnection->makeConnectToModel(&SafeObject::setValue, [this](QVariant value) { mConnection->makeConnectToModel(&SafeObject::setValue, [this](QVariant value) {
mConnection->invokeToCore([this, value]() { mConnection->invokeToCore([this, value]() {
// TODO : fix this properly
if (mCoreObject) mCoreObject->onSetValue(value); if (mCoreObject) mCoreObject->onSetValue(value);
}); });
}); });

View file

@ -32,7 +32,7 @@ Window {
onCallChanged: { onCallChanged: {
waitingTime.seconds = 0 waitingTime.seconds = 0
waitingTimer.restart() waitingTimer.restart()
console.log("call changed", call, waitingTime.seconds) console.log("call changed", call)
} }
property var callState: call.core.state property var callState: call.core.state
@ -195,8 +195,9 @@ Window {
color: DefaultStyle.grey_900 color: DefaultStyle.grey_900
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
spacing: 5 * DefaultStyle.dp spacing: 10 * DefaultStyle.dp
anchors.bottomMargin: 5 * DefaultStyle.dp anchors.bottomMargin: 10 * DefaultStyle.dp
anchors.topMargin: 10 * DefaultStyle.dp
Item { Item {
Layout.margins: 10 * DefaultStyle.dp Layout.margins: 10 * DefaultStyle.dp
Layout.fillWidth: true Layout.fillWidth: true
@ -276,11 +277,15 @@ Window {
bottomPadding: 8 * DefaultStyle.dp bottomPadding: 8 * DefaultStyle.dp
leftPadding: 10 * DefaultStyle.dp leftPadding: 10 * DefaultStyle.dp
rightPadding: 10 * DefaultStyle.dp rightPadding: 10 * DefaultStyle.dp
visible: mainWindow.call.core.isSecured width: 269 * DefaultStyle.dp
visible: mainWindow.call.core.peerSecured
onVisibleChanged: console.log("peer secured", mainWindow.call.core.peerSecured)
background: Rectangle { background: Rectangle {
anchors.fill: parent anchors.fill: parent
color: DefaultStyle.main2_0
border.color: DefaultStyle.info_500_main border.color: DefaultStyle.info_500_main
radius: 15 * DefaultStyle.dp border.width: 1 * DefaultStyle.dp
radius: 50 * DefaultStyle.dp
} }
contentItem: RowLayout { contentItem: RowLayout {
Image { Image {
@ -296,7 +301,6 @@ Window {
color: DefaultStyle.info_500_main color: DefaultStyle.info_500_main
font { font {
pixelSize: 14 * DefaultStyle.dp pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
} }
} }
} }
@ -481,13 +485,14 @@ Window {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: numPad.height Layout.preferredHeight: numPad.height
Layout.topMargin: 10 * DefaultStyle.dp Layout.topMargin: 10 * DefaultStyle.dp
property var callObj
NumericPad { NumericPad {
id: numPad id: numPad
width: parent.width width: parent.width
visible: parent.visible visible: parent.visible
closeButtonVisible: false closeButtonVisible: false
onLaunchCall: { onLaunchCall: {
UtilsCpp.createCall(dialerTextInput.text + "@sip.linphone.org") callObj = UtilsCpp.createCall(dialerTextInput.text + "@sip.linphone.org")
} }
} }
} }

View file

@ -119,11 +119,12 @@ ColumnLayout {
// height: image.height // height: image.height
image.source: AppIcons.phone image.source: AppIcons.phone
label: qsTr("Appel") label: qsTr("Appel")
property var callObj
button.onClicked: { button.onClicked: {
var addr = mainItem.contact.core.defaultAddress var addr = mainItem.contact.core.defaultAddress
var addressEnd = "@sip.linphone.org" var addressEnd = "@sip.linphone.org"
if (!addr.endsWith(addressEnd)) addr += addressEnd if (!addr.endsWith(addressEnd)) addr += addressEnd
UtilsCpp.createCall(addr) callObj = UtilsCpp.createCall(addr)
} }
} }
LabelButton { LabelButton {
@ -141,11 +142,12 @@ ColumnLayout {
// Layout.preferredHeight: image.height // Layout.preferredHeight: image.height
image.source: AppIcons.videoCamera image.source: AppIcons.videoCamera
label: qsTr("Appel Video") label: qsTr("Appel Video")
property var callObj
button.onClicked: { button.onClicked: {
var addr = mainItem.contact.core.defaultAddress var addr = mainItem.contact.core.defaultAddress
var addressEnd = "@sip.linphone.org" var addressEnd = "@sip.linphone.org"
if(!addr.endsWith(addressEnd)) addr += addressEnd if(!addr.endsWith(addressEnd)) addr += addressEnd
UtilsCpp.createCall(addr) callObj = UtilsCpp.createCall(addr)
console.log("[CallPage.qml] TODO : enable video") console.log("[CallPage.qml] TODO : enable video")
} }
} }

View file

@ -13,6 +13,10 @@ Window {
// TODO : handle this bool when security mode is implemented // TODO : handle this bool when security mode is implemented
property bool firstConnection: true property bool firstConnection: true
// access window properties from all its children
// (used in popupbutton to see if the popup exceed window height)
property Window mainApplicationWindow: mainWindow
function goToNewCall() { function goToNewCall() {
mainWindowStackView.replace(mainPage, StackView.Immediate) mainWindowStackView.replace(mainPage, StackView.Immediate)
mainWindowStackView.currentItem.goToNewCall() mainWindowStackView.currentItem.goToNewCall()

View file

@ -23,7 +23,7 @@ Control.Button {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: hovered ? Qt.PointingHandCursor : Qt.ArrowCursor cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
acceptedButtons: Qt.NoButton acceptedButtons: Qt.NoButton
} }
@ -44,7 +44,7 @@ Control.Button {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: hovered ? Qt.PointingHandCursor : Qt.ArrowCursor cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
} }
} }
MultiEffect { MultiEffect {

View file

@ -24,16 +24,17 @@ Item {
} }
underlineColor: DefaultStyle.main1_500_main underlineColor: DefaultStyle.main1_500_main
anchors.centerIn: parent anchors.centerIn: parent
width: parent.width width: parent.width - 30 * DefaultStyle.dp
modal: true modal: true
leftPadding: 15 * DefaultStyle.dp leftPadding: 15 * DefaultStyle.dp
rightPadding: 15 * DefaultStyle.dp rightPadding: 15 * DefaultStyle.dp
topPadding: 20 * DefaultStyle.dp topPadding: 20 * DefaultStyle.dp
bottomPadding: 25 * DefaultStyle.dp bottomPadding: 25 * DefaultStyle.dp
contentItem: ColumnLayout { contentItem: ColumnLayout {
spacing: 10 * DefaultStyle.dp
RowLayout { RowLayout {
Text { Text {
text: qsTr("Select channel") text: qsTr("Which channel do you choose?")
font { font {
pixelSize: 16 * DefaultStyle.dp pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp weight: 800 * DefaultStyle.dp
@ -53,83 +54,51 @@ Item {
onClicked: startCallPopup.close() onClicked: startCallPopup.close()
} }
} }
component AddressButton: Button { ListView {
property int index id: popuplist
property string label model: VariantList {
property string address model: startCallPopup.contact && startCallPopup.contact.core.allAddresses || []
id: channel }
// required property int index
leftPadding: 0
rightPadding: 0
// topPadding: 0
bottomPadding: 0
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: contentHeight
background: Item{} delegate: Item {
contentItem: ColumnLayout { width: parent.width
RowLayout { height: 56 * DefaultStyle.dp
ColumnLayout {
width: parent.width
anchors.verticalCenter: parent.verticalCenter
spacing: 10 * DefaultStyle.dp
ColumnLayout { ColumnLayout {
Text { Text {
Layout.leftMargin: 5 * DefaultStyle.dp Layout.leftMargin: 5 * DefaultStyle.dp
Layout.rightMargin: 5 * DefaultStyle.dp text: modelData.label
text: label
// TODO : change this with domain
font { font {
pixelSize: 14 * DefaultStyle.dp pixelSize: 13 * DefaultStyle.dp
weight: 700 * DefaultStyle.dp weight: 700 * DefaultStyle.dp
} }
} }
Text { Text {
Layout.leftMargin: 5 * DefaultStyle.dp Layout.leftMargin: 5 * DefaultStyle.dp
Layout.rightMargin: 5 * DefaultStyle.dp text: modelData.address
text: address
font { font {
pixelSize: 13 * DefaultStyle.dp pixelSize: 14 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp weight: 400 * DefaultStyle.dp
} }
} }
} }
Item {
Layout.fillWidth: true
}
}
Rectangle { Rectangle {
visible: index < selectedContactAddresses.count - 1 visible: index != popuplist.model.count - 1
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 1 * DefaultStyle.dp Layout.preferredHeight: 1 * DefaultStyle.dp
color: DefaultStyle.main2_200 color: DefaultStyle.main2_200
} }
} }
onClicked: mainItem.callButtonPressed(address) MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: mainItem.callButtonPressed(modelData.address)
} }
Repeater {
id: selectedContactAddresses
model: VariantList {
model: startCallPopup.contact && startCallPopup.contact.core.addresses || []
}
// model: startCallPopup.contact ? startCallPopup.contact.core.addresses : ""
// {label: "Work", address: "06000000000"},
// {label: "Personal", address: "060000000"}
//account.adresses
delegate: AddressButton {
// property int index
// property string label
// property string address
}
}
Repeater {
id: selectedContactPhoneNumbers
model: VariantList {
model: startCallPopup.contact && startCallPopup.contact.core.phoneNumbers || []
}
// model: startCallPopup.contact ? startCallPopup.contact.core.addresses : ""
// {label: "Work", address: "06000000000"},
// {label: "Personal", address: "060000000"}
//account.adresses
delegate: AddressButton {
// property int index
// property string label
// property string address
} }
} }
} }
@ -259,14 +228,18 @@ Item {
} }
} }
ContactsList{ ContactsList{
id: contactList
Layout.fillWidth: true Layout.fillWidth: true
contactMenuVisible: false contactMenuVisible: false
id: contactList
searchBarText: searchBar.text searchBarText: searchBar.text
onContactSelected: (contact) => { onContactSelected: (contact) => {
console.log("contact selected", contact) if (contact.core.allAddresses.length > 1) {
startCallPopup.contact = contact startCallPopup.contact = contact
startCallPopup.open() startCallPopup.open()
} else {
mainItem.callButtonPressed(contact.core.defaultAddress)
}
} }
} }
} }
@ -283,14 +256,25 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
initialHeadersVisible: false initialHeadersVisible: false
displayNameCapitalization: false
model: MagicSearchProxy { model: MagicSearchProxy {
searchText: searchBar.text.length === 0 ? "*" : searchBar.text searchText: searchBar.text.length === 0 ? "*" : searchBar.text
sourceFlags: LinphoneEnums.MagicSearchSource.FavoriteFriends sourceFlags: LinphoneEnums.MagicSearchSource.All
aggregationFlag: LinphoneEnums.MagicSearchAggregation.Friend aggregationFlag: LinphoneEnums.MagicSearchAggregation.Friend
} }
onContactSelected: (contact) => { onContactSelected: (contact) => {
if (contact.core.allAddresses.length > 1) {
startCallPopup.contact = contact startCallPopup.contact = contact
startCallPopup.open() startCallPopup.open()
} else {
var addressToCall = contact.core.defaultAddress.length === 0
? contact.core.phoneNumbers.length === 0
? ""
: contact.core.phoneNumbers[0].address
: contact.core.defaultAddress
if (addressToCall.length != 0) mainItem.callButtonPressed(addressToCall)
}
} }
} }
} }
@ -310,8 +294,9 @@ Item {
NumericPad { NumericPad {
id: numPad id: numPad
width: parent.width width: parent.width
property var callObj
onLaunchCall: { onLaunchCall: {
UtilsCpp.createCall(searchBar.text + "@sip.linphone.org") callObj = UtilsCpp.createCall(searchBar.text + "@sip.linphone.org")
// TODO : auto completion instead of sip linphone // TODO : auto completion instead of sip linphone
} }
} }

View file

@ -147,7 +147,7 @@ ColumnLayout {
TextInput { TextInput {
label: modelData.label label: modelData.label
onEditingFinished: { onEditingFinished: {
if (text.length != 0) mainItem.contact.core.setAddressAt(index, text) if (text.length != 0) mainItem.contact.core.setAddressAt(index, qsTr("Address SIP"), text)
} }
initialText: modelData.address initialText: modelData.address
backgroundColor: DefaultStyle.grey_0 backgroundColor: DefaultStyle.grey_0

View file

@ -15,6 +15,8 @@ ListView {
property bool hoverEnabled: true property bool hoverEnabled: true
property bool contactMenuVisible: true property bool contactMenuVisible: true
property bool initialHeadersVisible: true property bool initialHeadersVisible: true
property bool displayNameCapitalization: true
property FriendGui selectedContact: model.getAt(currentIndex) || null property FriendGui selectedContact: model.getAt(currentIndex) || null
@ -25,6 +27,7 @@ ListView {
signal contactSelected(var contact) signal contactSelected(var contact)
signal contactStarredChanged() signal contactStarredChanged()
signal contactDeletionRequested(FriendGui contact)
onContactStarredChanged: model.forceUpdate() onContactStarredChanged: model.forceUpdate()
@ -45,6 +48,7 @@ ListView {
} }
Text { Text {
id: initial id: initial
visible: mainItem.model.sourceFlags != LinphoneEnums.MagicSearchSource.All
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
Layout.preferredWidth: 20 * DefaultStyle.dp Layout.preferredWidth: 20 * DefaultStyle.dp
@ -72,7 +76,7 @@ ListView {
Text { Text {
text: itemDelegate.displayName text: itemDelegate.displayName
font.pixelSize: 14 * DefaultStyle.dp font.pixelSize: 14 * DefaultStyle.dp
font.capitalization: Font.Capitalize font.capitalization: mainItem.displayNameCapitalization ? Font.Capitalize : Font.MixedCase
} }
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
@ -137,7 +141,7 @@ ListView {
} }
} }
onClicked: { onClicked: {
modelData.core.remove() mainItem.contactDeletionRequested(modelData)
friendPopup.close() friendPopup.close()
} }
} }

View file

@ -1,4 +1,4 @@
import QtQuick 2.7 import QtQuick
import QtQuick.Controls 2.2 as Control import QtQuick.Controls 2.2 as Control
import QtQuick.Effects import QtQuick.Effects
import Linphone import Linphone
@ -39,6 +39,15 @@ Button {
y: mainItem.height y: mainItem.height
closePolicy: Popup.CloseOnPressOutsideParent |Popup.CloseOnPressOutside closePolicy: Popup.CloseOnPressOutsideParent |Popup.CloseOnPressOutside
onAboutToShow: {
var coord = mapToGlobal(mainItem.x, mainItem.y)
if (coord.y + popup.height >= mainApplicationWindow.height) {
y = -popup.height
} else {
y = mainItem.height
}
}
padding: 20 * DefaultStyle.dp padding: 20 * DefaultStyle.dp
background: Item { background: Item {

View file

@ -10,7 +10,9 @@ Control.Control {
leftPadding: 10 * DefaultStyle.dp leftPadding: 10 * DefaultStyle.dp
rightPadding: 10 * DefaultStyle.dp rightPadding: 10 * DefaultStyle.dp
background: Rectangle { background: Rectangle {
anchors.fill: parent // anchors.fill: parent
width: parent.width
height: parent.height
radius: 15 * DefaultStyle.dp radius: 15 * DefaultStyle.dp
color: mainItem.backgroundColor ? mainItem.backgroundColor : DefaultStyle.grey_0 color: mainItem.backgroundColor ? mainItem.backgroundColor : DefaultStyle.grey_0
} }

View file

@ -3,11 +3,9 @@ import QtQuick.Layouts
import Linphone import Linphone
Quick.Text { Quick.Text {
id: mainItem
property double scaleLettersFactor: 1. property double scaleLettersFactor: 1.
width: txtMeter.advanceWidth width: txtMeter.advanceWidth
id: innerItem
// Layout.preferredWidth: mainItem.width
// width: mainItem.width
font { font {
family: DefaultStyle.defaultFont family: DefaultStyle.defaultFont
pixelSize: 10 * DefaultStyle.dp pixelSize: 10 * DefaultStyle.dp
@ -18,12 +16,12 @@ Quick.Text {
elide: Quick.Text.ElideRight elide: Quick.Text.ElideRight
transformOrigin: Quick.Item.TopLeft transformOrigin: Quick.Item.TopLeft
transform: Quick.Scale { transform: Quick.Scale {
yScale: scaleLettersFactor//mainItem.scaleLettersFactor yScale: scaleLettersFactor
} }
Quick.TextMetrics { Quick.TextMetrics {
id: txtMeter id: txtMeter
text: innerItem.text text: mainItem.text
font: innerItem.font font: mainItem.font
} }
} }

View file

@ -156,23 +156,13 @@ AbstractMainPage {
clip: true clip: true
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
model: CallHistoryProxy{ model: CallHistoryProxy {
filterText: searchBar.text filterText: searchBar.text
} }
currentIndex: -1 currentIndex: -1
spacing: 10 * DefaultStyle.dp spacing: 10 * DefaultStyle.dp
highlightMoveDuration: 10
highlightMoveVelocity: -1
// highlightFollowsCurrentItem: true
highlight: Rectangle {
x: historyListView.x
width: historyListView.width
height: historyListView.height
color: DefaultStyle.main2_100
y: historyListView.currentItem? historyListView.currentItem.y : 0
}
delegate: Item { delegate: Item {
width:historyListView.width width:historyListView.width
@ -258,6 +248,7 @@ AbstractMainPage {
implicitHeight: 24 * DefaultStyle.dp implicitHeight: 24 * DefaultStyle.dp
Layout.rightMargin: 5 * DefaultStyle.dp Layout.rightMargin: 5 * DefaultStyle.dp
padding: 0 padding: 0
property var callObj
background: Item { background: Item {
visible: false visible: false
} }
@ -271,7 +262,7 @@ AbstractMainPage {
var addr = modelData.core.remoteAddress var addr = modelData.core.remoteAddress
var addressEnd = "@sip.linphone.org" var addressEnd = "@sip.linphone.org"
if (!addr.endsWith(addressEnd)) addr += addressEnd if (!addr.endsWith(addressEnd)) addr += addressEnd
UtilsCpp.createCall(addr) callObj = UtilsCpp.createCall(addr)
} }
} }
} }
@ -284,17 +275,22 @@ AbstractMainPage {
color: DefaultStyle.main2_500main color: DefaultStyle.main2_500main
visible: parent.containsMouse visible: parent.containsMouse
} }
Rectangle {
anchors.fill: parent
visible: historyListView.currentIndex === model.index
color: DefaultStyle.main2_100
}
onPressed: { onPressed: {
historyListView.currentIndex = model.index historyListView.currentIndex = model.index
} }
} }
} }
onCurrentIndexChanged: { onCurrentIndexChanged: {
positionViewAtIndex(currentIndex, ListView.Visible)
mainItem.selectedRowHistoryGui = model.getAt(currentIndex) mainItem.selectedRowHistoryGui = model.getAt(currentIndex)
} }
onVisibleChanged: { onVisibleChanged: {
if (!visible) currentIndex = -1 if (!visible) currentIndex = -1
console.log("visible", visible)
} }
Connections { Connections {
@ -352,11 +348,12 @@ AbstractMainPage {
// Layout.rightMargin: listStackView.sideMargin // Layout.rightMargin: listStackView.sideMargin
groupCallVisible: true groupCallVisible: true
searchBarColor: DefaultStyle.grey_100 searchBarColor: DefaultStyle.grey_100
property var callObj
onCallButtonPressed: (address) => { onCallButtonPressed: (address) => {
var addressEnd = "@sip.linphone.org" var addressEnd = "@sip.linphone.org"
if (!address.endsWith(addressEnd)) address += addressEnd if (!address.endsWith(addressEnd)) address += addressEnd
UtilsCpp.createCall(address) callObj = UtilsCpp.createCall(address)
// var window = UtilsCpp.getCallsWindow() // var window = UtilsCpp.getCallsWindow()
} }
} }
@ -416,7 +413,6 @@ AbstractMainPage {
detailOptions.close() detailOptions.close()
friendGui.core.givenName = UtilsCpp.getGivenNameFromFullName(contactDetail.contactName) friendGui.core.givenName = UtilsCpp.getGivenNameFromFullName(contactDetail.contactName)
friendGui.core.familyName = UtilsCpp.getFamilyNameFromFullName(contactDetail.contactName) friendGui.core.familyName = UtilsCpp.getFamilyNameFromFullName(contactDetail.contactName)
friendGui.core.appendAddress(contactDetail.contactAddress)
friendGui.core.defaultAddress = contactDetail.contactAddress friendGui.core.defaultAddress = contactDetail.contactAddress
rightPanelStackView.push(editContact, {"contact": friendGui, "title": qsTr("Ajouter contact"), "saveButtonText": qsTr("Créer")}) rightPanelStackView.push(editContact, {"contact": friendGui, "title": qsTr("Ajouter contact"), "saveButtonText": qsTr("Créer")})
} }
@ -452,7 +448,10 @@ AbstractMainPage {
} }
Connections { Connections {
target: deleteForUserPopup target: deleteForUserPopup
onAccepted: detailListView.model.removeEntriesWithFilter() onAccepted: {
detailListView.model.removeEntriesWithFilter()
mainItem.listViewUpdated()
}
} }
onClicked: { onClicked: {
detailOptions.close() detailOptions.close()
@ -461,34 +460,32 @@ AbstractMainPage {
} }
} }
} }
detailContent: Control.Control { detailContent: RoundedBackgroundControl {
id: detailControl id: detailControl
// Layout.fillWidth: true
Layout.fillHeight: true
Layout.preferredWidth: 360 * DefaultStyle.dp Layout.preferredWidth: 360 * DefaultStyle.dp
implicitHeight: 430 * DefaultStyle.dp + topPadding + bottomPadding
background: Rectangle { background: Rectangle {
id: detailListBackground id: detailListBackground
width: parent.width
height: detailListView.height
color: DefaultStyle.grey_0 color: DefaultStyle.grey_0
radius: 15 * DefaultStyle.dp radius: 15 * DefaultStyle.dp
anchors.fill: detailListView
} }
contentItem: ListView { ListView {
id: detailListView id: detailListView
width: parent.width width: parent.width
height: Math.min(detailControl.height, contentHeight) height: Math.min(detailControl.implicitHeight, contentHeight)
spacing: 20 * DefaultStyle.dp spacing: 20 * DefaultStyle.dp
clip: true clip: true
onCountChanged: {
mainItem.listViewUpdated()
}
model: CallHistoryProxy { model: CallHistoryProxy {
filterText: mainItem.selectedRowHistoryGui ? mainItem.selectedRowHistoryGui.core.remoteAddress : "" filterText: mainItem.selectedRowHistoryGui ? mainItem.selectedRowHistoryGui.core.remoteAddress : ""
} }
delegate: Item { delegate: Item {
width:detailListView.width width:detailListView.width
height: 56 * DefaultStyle.dp height: 56 * DefaultStyle.dp
@ -556,6 +553,9 @@ AbstractMainPage {
} }
} }
} }
Item{
Layout.fillHeight: true
}
} }
} }
Component { Component {

View file

@ -32,6 +32,13 @@ AbstractMainPage {
listStackView.replace(newCallItem) listStackView.replace(newCallItem)
} }
Dialog {
id: dialog
property var contact
text: (contact ? contact.core.displayName : "Contact") + " is about to be deleted. Do you want to continue ?"
onAccepted: contact.core.remove()
}
leftPanelContent: ColumnLayout { leftPanelContent: ColumnLayout {
id: leftPanel id: leftPanel
Layout.fillWidth: true Layout.fillWidth: true
@ -164,6 +171,10 @@ AbstractMainPage {
} }
mainItem.selectedContact = selectedContact mainItem.selectedContact = selectedContact
} }
onContactDeletionRequested: (contact) => {
dialog.contact = contact
dialog.open()
}
} }
} }
ColumnLayout { ColumnLayout {
@ -205,6 +216,10 @@ AbstractMainPage {
} }
mainItem.selectedContact = selectedContact mainItem.selectedContact = selectedContact
} }
onContactDeletionRequested: (contact) => {
dialog.contact = contact
dialog.open()
}
} }
} }
} }
@ -274,7 +289,7 @@ AbstractMainPage {
height: contentHeight height: contentHeight
clip: true clip: true
model: VariantList { model: VariantList {
model: mainItem.selectedContact ? mainItem.selectedContact.core.allAdresses : [] model: mainItem.selectedContact ? mainItem.selectedContact.core.allAddresses : []
} }
// model: contactDetail.selectedContact && contactDetail.selectedContact.core.addresses // model: contactDetail.selectedContact && contactDetail.selectedContact.core.addresses
delegate: Item { delegate: Item {
@ -317,6 +332,7 @@ AbstractMainPage {
background: Item{} background: Item{}
Layout.preferredWidth: 24 * DefaultStyle.dp Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp Layout.preferredHeight: 24 * DefaultStyle.dp
property var callObj
contentItem: Image { contentItem: Image {
anchors.fill: parent anchors.fill: parent
source: AppIcons.phone source: AppIcons.phone
@ -324,7 +340,7 @@ AbstractMainPage {
height: 24 * DefaultStyle.dp height: 24 * DefaultStyle.dp
} }
onClicked: { onClicked: {
UtilsCpp.createCall(modelData.address) callObj = UtilsCpp.createCall(modelData.address)
} }
} }
} }
@ -550,7 +566,11 @@ AbstractMainPage {
iconSource: AppIcons.trashCan iconSource: AppIcons.trashCan
color: DefaultStyle.danger_500main color: DefaultStyle.danger_500main
text: qsTr("Delete this contact") text: qsTr("Delete this contact")
onClicked: mainItem.selectedContact.core.remove() onClicked: {
// mainItem.selectedContact.core.remove()
dialog.contact = mainItem.selectedContact
dialog.open()
}
} }
} }
} }