Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linphone-desktop
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
linphone-desktop
Commits
d308d0a3
Commit
d308d0a3
authored
Dec 15, 2016
by
Ronan Abhamon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(ui/views/App/MainWindow/ContactEdit): supports the add of new contacts
parent
338fe8c0
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
322 additions
and
160 deletions
+322
-160
edit_hovered.svg
tests/assets/images/edit_hovered.svg
+13
-0
edit_normal.svg
tests/assets/images/edit_normal.svg
+13
-0
edit_pressed.svg
tests/assets/images/edit_pressed.svg
+13
-0
resources.qrc
tests/resources.qrc
+3
-0
ContactModel.cpp
tests/src/components/contact/ContactModel.cpp
+14
-0
ContactModel.hpp
tests/src/components/contact/ContactModel.hpp
+1
-0
VcardModel.cpp
tests/src/components/contact/VcardModel.cpp
+27
-31
VcardModel.hpp
tests/src/components/contact/VcardModel.hpp
+3
-2
ContactsListModel.cpp
tests/src/components/contacts/ContactsListModel.cpp
+26
-7
ContactsListModel.hpp
tests/src/components/contacts/ContactsListModel.hpp
+1
-0
CoreManager.cpp
tests/src/components/core/CoreManager.cpp
+6
-3
CoreManager.hpp
tests/src/components/core/CoreManager.hpp
+6
-2
Colors.qml
tests/ui/modules/Common/Colors.qml
+3
-3
AbstractTextButton.qml
tests/ui/modules/Common/Form/AbstractTextButton.qml
+58
-27
ListForm.qml
tests/ui/modules/Common/Form/ListForm.qml
+32
-36
TextButtonA.qml
tests/ui/modules/Common/Form/TextButtonA.qml
+3
-1
TextButtonB.qml
tests/ui/modules/Common/Form/TextButtonB.qml
+3
-1
TextButtonAStyle.qml
tests/ui/modules/Common/Styles/Form/TextButtonAStyle.qml
+3
-1
TextButtonBStyle.qml
tests/ui/modules/Common/Styles/Form/TextButtonBStyle.qml
+3
-1
ContactEdit.qml
tests/ui/views/App/MainWindow/ContactEdit.qml
+91
-45
No files found.
tests/assets/images/edit_hovered.svg
0 → 100644
View file @
d308d0a3
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"40px"
height=
"40px"
viewBox=
"0 0 40 40"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<!-- Generator: Sketch 41 (35326) - http://www.bohemiancoding.com/sketch -->
<title>
options_over
</title>
<desc>
Created with Sketch.
</desc>
<defs></defs>
<g
id=
"Symbols"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
id=
"options_over"
>
<path
d=
"M20,40 C31.045695,40 40,31.045695 40,20 C40,8.954305 31.045695,0 20,0 C8.954305,0 0,8.954305 0,20 C0,31.045695 8.954305,40 20,40 Z"
fill=
"#4B5964"
></path>
<path
d=
"M29.0873544,21.9006986 L29.0873544,18.0990443 L27.457167,18.0990443 C27.276035,17.3980628 26.9959394,16.7371962 26.6347091,16.1290447 L27.7891991,14.9803711 L25.0877236,12.2919042 L23.933492,13.441092 C23.3229145,13.0816012 22.6583335,12.8028543 21.9537018,12.6225946 L21.9537018,11 L18.133911,11 L18.133911,12.6225946 C17.4292793,12.8028543 16.765215,13.0816012 16.1538624,13.441092 L14.9993724,12.2919042 L12.298672,14.9803711 L13.453162,16.1290447 C13.0916733,16.7369391 12.8115777,17.3980628 12.6301874,18.0990443 L11,18.0990443 L11,21.9006986 L12.6301874,21.9006986 C12.8115777,22.6019372 13.0916733,23.2630609 13.4523869,23.8712124 L12.298672,25.0196289 L14.9998892,27.7078387 L16.1538624,26.5591651 C16.765215,26.9183988 17.4292793,27.1974028 18.133911,27.3774054 L18.133911,29 L21.9537018,29 L21.9537018,27.3774054 C22.6585919,27.1974028 23.3229145,26.9183988 23.9337503,26.5591651 L25.0877236,27.7078387 L27.7891991,25.0196289 L26.6347091,23.8712124 C26.9959394,23.2630609 27.2762934,22.6019372 27.457167,21.9006986 L29.0873544,21.9006986 L29.0873544,21.9006986 Z M15.9908179,20.0001286 C15.9908179,22.227789 17.8054963,24.0334719 20.0439356,24.0334719 C22.2818581,24.0334719 24.0965365,22.227789 24.0965365,20.0001286 C24.0965365,17.7729825 22.2818581,15.9667852 20.0439356,15.9667852 C17.8054963,15.9667852 15.9908179,17.7729825 15.9908179,20.0001286 L15.9908179,20.0001286 Z"
stroke=
"#FFFFFF"
stroke-width=
"1.5"
stroke-linecap=
"round"
stroke-linejoin=
"round"
></path>
</g>
</g>
</svg>
\ No newline at end of file
tests/assets/images/edit_normal.svg
0 → 100644
View file @
d308d0a3
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"40px"
height=
"40px"
viewBox=
"0 0 40 40"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<!-- Generator: Sketch 41 (35326) - http://www.bohemiancoding.com/sketch -->
<title>
options_default
</title>
<desc>
Created with Sketch.
</desc>
<defs></defs>
<g
id=
"Symbols"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
id=
"options_default"
>
<path
d=
"M20,40 C31.045695,40 40,31.045695 40,20 C40,8.954305 31.045695,0 20,0 C8.954305,0 0,8.954305 0,20 C0,31.045695 8.954305,40 20,40 Z"
fill=
"#96A6B1"
></path>
<path
d=
"M29.0873544,21.9006986 L29.0873544,18.0990443 L27.457167,18.0990443 C27.276035,17.3980628 26.9959394,16.7371962 26.6347091,16.1290447 L27.7891991,14.9803711 L25.0877236,12.2919042 L23.933492,13.441092 C23.3229145,13.0816012 22.6583335,12.8028543 21.9537018,12.6225946 L21.9537018,11 L18.133911,11 L18.133911,12.6225946 C17.4292793,12.8028543 16.765215,13.0816012 16.1538624,13.441092 L14.9993724,12.2919042 L12.298672,14.9803711 L13.453162,16.1290447 C13.0916733,16.7369391 12.8115777,17.3980628 12.6301874,18.0990443 L11,18.0990443 L11,21.9006986 L12.6301874,21.9006986 C12.8115777,22.6019372 13.0916733,23.2630609 13.4523869,23.8712124 L12.298672,25.0196289 L14.9998892,27.7078387 L16.1538624,26.5591651 C16.765215,26.9183988 17.4292793,27.1974028 18.133911,27.3774054 L18.133911,29 L21.9537018,29 L21.9537018,27.3774054 C22.6585919,27.1974028 23.3229145,26.9183988 23.9337503,26.5591651 L25.0877236,27.7078387 L27.7891991,25.0196289 L26.6347091,23.8712124 C26.9959394,23.2630609 27.2762934,22.6019372 27.457167,21.9006986 L29.0873544,21.9006986 L29.0873544,21.9006986 Z M15.9908179,20.0001286 C15.9908179,22.227789 17.8054963,24.0334719 20.0439356,24.0334719 C22.2818581,24.0334719 24.0965365,22.227789 24.0965365,20.0001286 C24.0965365,17.7729825 22.2818581,15.9667852 20.0439356,15.9667852 C17.8054963,15.9667852 15.9908179,17.7729825 15.9908179,20.0001286 L15.9908179,20.0001286 Z"
stroke=
"#FFFFFF"
stroke-width=
"1.5"
stroke-linecap=
"round"
stroke-linejoin=
"round"
></path>
</g>
</g>
</svg>
\ No newline at end of file
tests/assets/images/edit_pressed.svg
0 → 100644
View file @
d308d0a3
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"40px"
height=
"40px"
viewBox=
"0 0 40 40"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<!-- Generator: Sketch 41 (35326) - http://www.bohemiancoding.com/sketch -->
<title>
options_clic
</title>
<desc>
Created with Sketch.
</desc>
<defs></defs>
<g
id=
"Symbols"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
id=
"options_clic"
>
<path
d=
"M20,40 C31.045695,40 40,31.045695 40,20 C40,8.954305 31.045695,0 20,0 C8.954305,0 0,8.954305 0,20 C0,31.045695 8.954305,40 20,40 Z"
fill=
"#FF5E00"
></path>
<path
d=
"M29.0873544,21.9006986 L29.0873544,18.0990443 L27.457167,18.0990443 C27.276035,17.3980628 26.9959394,16.7371962 26.6347091,16.1290447 L27.7891991,14.9803711 L25.0877236,12.2919042 L23.933492,13.441092 C23.3229145,13.0816012 22.6583335,12.8028543 21.9537018,12.6225946 L21.9537018,11 L18.133911,11 L18.133911,12.6225946 C17.4292793,12.8028543 16.765215,13.0816012 16.1538624,13.441092 L14.9993724,12.2919042 L12.298672,14.9803711 L13.453162,16.1290447 C13.0916733,16.7369391 12.8115777,17.3980628 12.6301874,18.0990443 L11,18.0990443 L11,21.9006986 L12.6301874,21.9006986 C12.8115777,22.6019372 13.0916733,23.2630609 13.4523869,23.8712124 L12.298672,25.0196289 L14.9998892,27.7078387 L16.1538624,26.5591651 C16.765215,26.9183988 17.4292793,27.1974028 18.133911,27.3774054 L18.133911,29 L21.9537018,29 L21.9537018,27.3774054 C22.6585919,27.1974028 23.3229145,26.9183988 23.9337503,26.5591651 L25.0877236,27.7078387 L27.7891991,25.0196289 L26.6347091,23.8712124 C26.9959394,23.2630609 27.2762934,22.6019372 27.457167,21.9006986 L29.0873544,21.9006986 L29.0873544,21.9006986 Z M15.9908179,20.0001286 C15.9908179,22.227789 17.8054963,24.0334719 20.0439356,24.0334719 C22.2818581,24.0334719 24.0965365,22.227789 24.0965365,20.0001286 C24.0965365,17.7729825 22.2818581,15.9667852 20.0439356,15.9667852 C17.8054963,15.9667852 15.9908179,17.7729825 15.9908179,20.0001286 L15.9908179,20.0001286 Z"
stroke=
"#FFFFFF"
stroke-width=
"1.5"
stroke-linecap=
"round"
stroke-linejoin=
"round"
></path>
</g>
</g>
</svg>
\ No newline at end of file
tests/resources.qrc
View file @
d308d0a3
...
...
@@ -53,6 +53,9 @@
<file>
assets/images/delete_hovered.svg
</file>
<file>
assets/images/delete_normal.svg
</file>
<file>
assets/images/delete_pressed.svg
</file>
<file>
assets/images/edit_hovered.svg
</file>
<file>
assets/images/edit_normal.svg
</file>
<file>
assets/images/edit_pressed.svg
</file>
<file>
assets/images/ended_call.svg
</file>
<file>
assets/images/filter.svg
</file>
<file>
assets/images/fullscreen_hovered.svg
</file>
...
...
tests/src/components/contact/ContactModel.cpp
View file @
d308d0a3
#include <QtDebug>
#include "../../app/App.hpp"
#include "ContactModel.hpp"
...
...
@@ -16,6 +18,18 @@ ContactModel::ContactModel (shared_ptr<linphone::Friend> linphone_friend) {
App
::
getInstance
()
->
getEngine
()
->
setObjectOwnership
(
m_vcard
.
get
(),
QQmlEngine
::
CppOwnership
);
}
ContactModel
::
ContactModel
(
VcardModel
*
vcard
)
{
QQmlEngine
*
engine
=
App
::
getInstance
()
->
getEngine
();
if
(
engine
->
objectOwnership
(
vcard
)
==
QQmlEngine
::
CppOwnership
)
throw
std
::
invalid_argument
(
"A contact is already linked to this vcard."
);
m_linphone_friend
=
linphone
::
Friend
::
newFromVcard
(
vcard
->
m_vcard
);
m_linphone_friend
->
setData
(
NAME
,
*
this
);
m_vcard
.
reset
(
vcard
);
engine
->
setObjectOwnership
(
vcard
,
QQmlEngine
::
CppOwnership
);
}
Presence
::
PresenceStatus
ContactModel
::
getPresenceStatus
()
const
{
return
Presence
::
PresenceStatus
::
Offline
;
}
...
...
tests/src/components/contact/ContactModel.hpp
View file @
d308d0a3
...
...
@@ -22,6 +22,7 @@ class ContactModel : public QObject {
public:
ContactModel
(
std
::
shared_ptr
<
linphone
::
Friend
>
linphone_friend
);
ContactModel
(
VcardModel
*
vcard
);
static
const
char
*
NAME
;
...
...
tests/src/components/contact/VcardModel.cpp
View file @
d308d0a3
...
...
@@ -109,8 +109,7 @@ bool VcardModel::setAvatar (const QString &path) {
}
// 4. Update.
shared_ptr
<
belcard
::
BelCardPhoto
>
photo
=
belcard
::
BelCardGeneric
::
create
<
belcard
::
BelCardPhoto
>
();
shared_ptr
<
belcard
::
BelCardPhoto
>
photo
=
belcard
::
BelCardGeneric
::
create
<
belcard
::
BelCardPhoto
>
();
photo
->
setValue
(
VCARD_SCHEME
+
::
Utils
::
qStringToLinphoneString
(
file_id
));
if
(
!
belcard
->
addPhoto
(
photo
))
...
...
@@ -145,8 +144,7 @@ bool VcardModel::setAddress (const QVariantMap &address) {
while
(
!
addresses
.
empty
())
belcard
->
removeAddress
(
addresses
.
front
());
shared_ptr
<
belcard
::
BelCardAddress
>
belcard_address
=
belcard
::
BelCardGeneric
::
create
<
belcard
::
BelCardAddress
>
();
shared_ptr
<
belcard
::
BelCardAddress
>
belcard_address
=
belcard
::
BelCardGeneric
::
create
<
belcard
::
BelCardAddress
>
();
belcard_address
->
setStreet
(
::
Utils
::
qStringToLinphoneString
(
address
[
"street"
].
toString
()));
belcard_address
->
setLocality
(
::
Utils
::
qStringToLinphoneString
(
address
[
"locality"
].
toString
()));
...
...
@@ -163,42 +161,35 @@ bool VcardModel::setAddress (const QVariantMap &address) {
QVariantList
VcardModel
::
getSipAddresses
()
const
{
QVariantList
list
;
for
(
const
auto
&
address
:
m_vcard
->
get
SipAddresses
())
list
.
append
(
::
Utils
::
linphoneStringToQString
(
address
->
asString
()));
for
(
const
auto
&
address
:
m_vcard
->
get
Belcard
()
->
getImpp
())
list
.
append
(
::
Utils
::
linphoneStringToQString
(
address
->
getValue
()));
return
list
;
}
bool
VcardModel
::
addSipAddress
(
const
QString
&
sip_address
)
{
shared_ptr
<
linphone
::
Address
>
address
=
CoreManager
::
getInstance
()
->
getCore
()
->
createAddress
(
::
Utils
::
qStringToLinphoneString
(
sip_address
)
);
shared_ptr
<
belcard
::
BelCard
>
belcard
=
m_vcard
->
getBelcard
();
shared_ptr
<
belcard
::
BelCardImpp
>
value
=
belcard
::
BelCardGeneric
::
create
<
belcard
::
BelCardImpp
>
();
value
->
setValue
(
::
Utils
::
qStringToLinphoneString
(
sip_address
));
qInfo
()
<<
QStringLiteral
(
"Add new sip address: `%1`."
).
arg
(
sip_address
);
if
(
!
address
)
{
qWarning
()
<<
QStringLiteral
(
"Unable to add
invalid
sip address: `%1`."
).
arg
(
sip_address
);
if
(
!
belcard
->
addImpp
(
value
)
)
{
qWarning
()
<<
QStringLiteral
(
"Unable to add sip address: `%1`."
).
arg
(
sip_address
);
return
false
;
}
qInfo
()
<<
QStringLiteral
(
"Add new sip address: `%1`."
).
arg
(
sip_address
);
m_vcard
->
addSipAddress
(
address
->
asStringUriOnly
());
emit
vcardUpdated
();
return
true
;
}
void
VcardModel
::
removeSipAddress
(
const
QString
&
sip_address
)
{
list
<
shared_ptr
<
linphone
::
Address
>
>
addresses
=
m_vcard
->
getSipAddresses
();
string
match
=
::
Utils
::
qStringToLinphoneString
(
sip_address
);
auto
it
=
find_if
(
addresses
.
cbegin
(),
addresses
.
cend
(),
[
&
match
](
const
shared_ptr
<
linphone
::
Address
>
&
address
)
{
return
match
==
address
->
asString
();
}
);
shared_ptr
<
belcard
::
BelCard
>
belcard
=
m_vcard
->
getBelcard
();
list
<
shared_ptr
<
belcard
::
BelCardImpp
>
>
addresses
=
belcard
->
getImpp
();
shared_ptr
<
belcard
::
BelCardImpp
>
value
=
findBelCardValue
(
addresses
,
sip_address
);
if
(
it
==
addresses
.
cend
())
{
qWarning
()
<<
QStringLiteral
(
"Unable to found sip address: `%1`."
)
.
arg
(
sip_address
);
if
(
!
value
)
{
qWarning
()
<<
QStringLiteral
(
"Unable to remove sip address: `%1`."
).
arg
(
sip_address
);
return
;
}
...
...
@@ -209,7 +200,7 @@ void VcardModel::removeSipAddress (const QString &sip_address) {
}
qInfo
()
<<
QStringLiteral
(
"Remove sip address: `%1`."
).
arg
(
sip_address
);
m_vcard
->
removeSipAddress
((
*
it
)
->
asStringUriOnly
()
);
belcard
->
removeImpp
(
value
);
emit
vcardUpdated
();
}
...
...
@@ -241,8 +232,10 @@ bool VcardModel::addCompany (const QString &company) {
qInfo
()
<<
QStringLiteral
(
"Add new company: `%1`."
).
arg
(
company
);
if
(
!
belcard
->
addRole
(
value
))
if
(
!
belcard
->
addRole
(
value
))
{
qWarning
()
<<
QStringLiteral
(
"Unable to add company: `%1`."
).
arg
(
company
);
return
false
;
}
emit
vcardUpdated
();
return
true
;
...
...
@@ -285,14 +278,15 @@ QVariantList VcardModel::getEmails () const {
bool
VcardModel
::
addEmail
(
const
QString
&
email
)
{
shared_ptr
<
belcard
::
BelCard
>
belcard
=
m_vcard
->
getBelcard
();
shared_ptr
<
belcard
::
BelCardEmail
>
value
=
belcard
::
BelCardGeneric
::
create
<
belcard
::
BelCardEmail
>
();
shared_ptr
<
belcard
::
BelCardEmail
>
value
=
belcard
::
BelCardGeneric
::
create
<
belcard
::
BelCardEmail
>
();
value
->
setValue
(
::
Utils
::
qStringToLinphoneString
(
email
));
qInfo
()
<<
QStringLiteral
(
"Add new email: `%1`."
).
arg
(
email
);
if
(
!
belcard
->
addEmail
(
value
))
if
(
!
belcard
->
addEmail
(
value
))
{
qWarning
()
<<
QStringLiteral
(
"Unable to add email: `%1`."
).
arg
(
email
);
return
false
;
}
emit
vcardUpdated
();
return
true
;
...
...
@@ -340,8 +334,10 @@ bool VcardModel::addUrl (const QString &url) {
qInfo
()
<<
QStringLiteral
(
"Add new url: `%1`."
).
arg
(
url
);
if
(
!
belcard
->
addURL
(
value
))
if
(
!
belcard
->
addURL
(
value
))
{
qWarning
()
<<
QStringLiteral
(
"Unable to add url: `%1`."
).
arg
(
url
);
return
false
;
}
emit
vcardUpdated
();
return
true
;
...
...
tests/src/components/contact/VcardModel.hpp
View file @
d308d0a3
...
...
@@ -17,11 +17,13 @@ class VcardModel : public QObject {
Q_PROPERTY
(
QVariantList
emails
READ
getEmails
NOTIFY
vcardUpdated
);
Q_PROPERTY
(
QVariantList
urls
READ
getUrls
NOTIFY
vcardUpdated
);
friend
class
Contact
sListProxy
Model
;
friend
class
ContactModel
;
public:
VcardModel
(
std
::
shared_ptr
<
linphone
::
Vcard
>
vcard
)
:
m_vcard
(
vcard
)
{}
QString
getUsername
()
const
;
~
VcardModel
()
=
default
;
public
slots
:
...
...
@@ -45,7 +47,6 @@ signals:
void
vcardUpdated
();
private:
QString
getUsername
()
const
;
void
setUsername
(
const
QString
&
username
);
QString
getAvatar
()
const
;
...
...
tests/src/components/contacts/ContactsListModel.cpp
View file @
d308d0a3
...
...
@@ -27,7 +27,7 @@ ContactsListModel::ContactsListModel (QObject *parent) : QAbstractListModel(pare
}
}
int
ContactsListModel
::
rowCount
(
const
QModelIndex
&
)
const
{
int
ContactsListModel
::
rowCount
(
const
QModelIndex
&
)
const
{
return
m_list
.
count
();
}
...
...
@@ -49,8 +49,8 @@ QVariant ContactsListModel::data (const QModelIndex &index, int role) const {
return
QVariant
();
}
bool
ContactsListModel
::
removeRow
(
int
row
,
const
QModelIndex
&
)
{
return
removeRows
(
row
,
1
);
bool
ContactsListModel
::
removeRow
(
int
row
,
const
QModelIndex
&
parent
)
{
return
removeRows
(
row
,
1
,
parent
);
}
bool
ContactsListModel
::
removeRows
(
int
row
,
int
count
,
const
QModelIndex
&
parent
)
{
...
...
@@ -76,19 +76,38 @@ bool ContactsListModel::removeRows (int row, int count, const QModelIndex &paren
// -----------------------------------------------------------------------------
ContactModel
*
ContactsListModel
::
mapSipAddressToContact
(
const
QString
&
sipAddress
)
const
{
// TODO: Maybe use a hashtable in future version to get a lower cost?
shared_ptr
<
linphone
::
Friend
>
friend_
=
m_linphone_friends
->
findFriendByUri
(
::
Utils
::
qStringToLinphoneString
(
sipAddress
)
);
if
(
!
friend_
)
{
qInfo
()
<<
QStringLiteral
(
"Unable to map sip address: `%1`."
).
arg
(
sipAddress
);
if
(
!
friend_
)
return
nullptr
;
}
return
&
friend_
->
getData
<
ContactModel
>
(
ContactModel
::
NAME
);
}
void
ContactsListModel
::
addContact
(
VcardModel
*
vcard
)
{
ContactModel
*
contact
=
new
ContactModel
(
vcard
);
App
::
getInstance
()
->
getEngine
()
->
setObjectOwnership
(
contact
,
QQmlEngine
::
CppOwnership
);
qInfo
()
<<
"Add contact:"
<<
contact
;
if
(
m_linphone_friends
->
addFriend
(
contact
->
m_linphone_friend
)
!=
linphone
::
FriendListStatus
::
FriendListStatusOK
)
{
qWarning
()
<<
"Unable to add friend from vcard:"
<<
vcard
;
delete
contact
;
return
;
}
int
row
=
rowCount
();
beginInsertRows
(
QModelIndex
(),
row
,
row
);
m_list
<<
contact
;
endInsertRows
();
}
void
ContactsListModel
::
removeContact
(
ContactModel
*
contact
)
{
qInfo
()
<<
"Removing contact:"
<<
contact
;
...
...
tests/src/components/contacts/ContactsListModel.hpp
View file @
d308d0a3
...
...
@@ -27,6 +27,7 @@ public:
public
slots
:
ContactModel
*
mapSipAddressToContact
(
const
QString
&
sipAddress
)
const
;
void
addContact
(
VcardModel
*
vcard
);
void
removeContact
(
ContactModel
*
contact
);
private:
...
...
tests/src/components/core/CoreManager.cpp
View file @
d308d0a3
...
...
@@ -6,12 +6,15 @@
CoreManager
*
CoreManager
::
m_instance
=
nullptr
;
CoreManager
::
CoreManager
(
QObject
*
parent
)
:
QObject
(
parent
),
m_core
(
linphone
::
Factory
::
get
()
->
createCore
(
nullptr
,
""
,
""
,
nullptr
)
)
{
CoreManager
::
CoreManager
(
QObject
*
parent
)
:
QObject
(
parent
),
m_core
(
linphone
::
Factory
::
get
()
->
createCore
(
nullptr
,
""
,
""
,
nullptr
))
{
setDatabasesPaths
();
}
VcardModel
*
CoreManager
::
createDetachedVcardModel
()
{
return
new
VcardModel
(
linphone
::
Factory
::
get
()
->
createVcard
());
}
void
CoreManager
::
setDatabasesPaths
()
{
std
::
string
database_path
;
...
...
tests/src/components/core/CoreManager.hpp
View file @
d308d0a3
...
...
@@ -4,6 +4,8 @@
#include <QObject>
#include <linphone++/linphone.hh>
#include "../contact/VcardModel.hpp"
// ===================================================================
class
CoreManager
:
public
QObject
{
...
...
@@ -24,14 +26,16 @@ public:
return
m_core
;
}
public
slots
:
VcardModel
*
createDetachedVcardModel
();
private:
CoreManager
(
QObject
*
parent
=
Q_NULLPTR
);
void
setDatabasesPaths
();
static
CoreManager
*
m_instance
;
std
::
shared_ptr
<
linphone
::
Core
>
m_core
;
static
CoreManager
*
m_instance
;
};
#endif // CORE_MANAGER_H_
tests/ui/modules/Common/Colors.qml
View file @
d308d0a3
pragma
Singleton
import
QtQuick
2.7
// ===================================================================
// ===================================================================
==========
QtObject
{
property
color
a
:
'
transparent
'
property
color
o
:
'
#232323
'
// TextButtonA Hovered.
property
color
q
:
'
#E6E6E6
'
property
color
d
:
'
#5A585B
'
...
...
@@ -24,6 +22,7 @@ QtObject {
property
color
g20
:
'
#336B7A86
'
property
color
h
:
'
#687680
'
property
color
i
:
'
#FE5E00
'
property
color
i30
:
'
#4DFE5E00
'
property
color
j
:
'
#4B5964
'
property
color
j75
:
'
#BF4B5964
'
property
color
k
:
'
#FFFFFF
'
...
...
@@ -31,6 +30,7 @@ QtObject {
property
color
l
:
'
#000000
'
property
color
m
:
'
#D1D1D1
'
property
color
n
:
'
#C0C0C0
'
property
color
o
:
'
#232323
'
property
color
p
:
'
#E2E9EF
'
property
color
r
:
'
#595759
'
property
color
s
:
'
#D64D00
'
...
...
tests/ui/modules/Common/Form/AbstractTextButton.qml
View file @
d308d0a3
...
...
@@ -3,48 +3,79 @@ import QtQuick.Controls 2.0
import
Common
.
Styles
1.0
// ===================================================================
// ===================================================================
==========
Button
{
id
:
b
utton
Item
{
id
:
wrappedB
utton
property
color
colorDisabled
property
color
colorHovered
property
color
colorNormal
property
color
colorPressed
// By default textColorNormal is the hovered/pressed text color.
property
color
textColorDisabled
property
color
textColorHovered
:
textColorNormal
property
color
textColorNormal
property
color
textColorPressed
:
textColorNormal
background
:
Rectangle
{
color
:
button
.
down
property
alias
text
:
button
.
text
property
bool
enabled
:
true
signal
clicked
// ---------------------------------------------------------------------------
function
_getBackgroundColor
()
{
if
(
!
wrappedButton
.
enabled
)
{
return
colorDisabled
}
return
button
.
down
?
colorPressed
:
(
button
.
hovered
?
colorHovered
:
colorNormal
)
implicitHeight
:
AbstractTextButtonStyle
.
background
.
height
implicitWidth
:
AbstractTextButtonStyle
.
background
.
width
radius
:
AbstractTextButtonStyle
.
background
.
radius
:
(
button
.
hovered
?
colorHovered
:
colorNormal
)
}
contentItem
:
Text
{
color
:
button
.
down
function
_getTextColor
()
{
if
(
!
wrappedButton
.
enabled
)
{
return
textColorDisabled
}
return
button
.
down
?
textColorPressed
:
(
button
.
hovered
?
textColorHovered
:
textColorNormal
)
font
{
bold
:
true
pointSize
:
AbstractTextButtonStyle
.
text
.
fontSize
:
(
button
.
hovered
?
textColorHovered
:
textColorNormal
)
}
// ---------------------------------------------------------------------------
implicitHeight
:
button
.
height
implicitWidth
:
button
.
width
// ---------------------------------------------------------------------------
Button
{
id
:
button
background
:
Rectangle
{
color
:
_getBackgroundColor
()
implicitHeight
:
AbstractTextButtonStyle
.
background
.
height
implicitWidth
:
AbstractTextButtonStyle
.
background
.
width
radius
:
AbstractTextButtonStyle
.
background
.
radius
}
contentItem
:
Text
{
color
:
_getTextColor
()
font
{
bold
:
true
pointSize
:
AbstractTextButtonStyle
.
text
.
fontSize
}
elide
:
Text
.
ElideRight
horizontalAlignment
:
Text
.
AlignHCenter
text
:
button
.
text
verticalAlignment
:
Text
.
AlignVCenter
}
hoverEnabled
:
true
elide
:
Text
.
ElideRight
horizontalAlignment
:
Text
.
AlignHCenter
text
:
button
.
text
verticalAlignment
:
Text
.
AlignVCenter
onClicked
:
wrappedButton
.
enabled
&&
parent
.
clicked
()
}
hoverEnabled
:
true
}
tests/ui/modules/Common/Form/ListForm.qml
View file @
d308d0a3
...
...
@@ -5,21 +5,23 @@ import Common 1.0
import
Common
.
Styles
1.0
import
Utils
1.0
// ===================================================================
// ===================================================================
==========
RowLayout
{
id
:
listForm
property
alias
placeholder
:
placeholder
.
text
property
alias
title
:
text
.
text
property
bool
readOnly
:
false
property
int
inputMethodHints
property
var
defaultData
:
[]
property
var
minValues
readonly
property
int
count
:
values
.
count
signal
changed
(
int
index
,
string
default
_value
,
string
new_v
alue
)
signal
changed
(
int
index
,
string
default
Value
,
string
newV
alue
)
signal
removed
(
int
index
,
string
value
)
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
function
setInvalid
(
index
,
status
)
{
Utils
.
assert
(
...
...
@@ -48,47 +50,41 @@ RowLayout {
}
function
_handleEditionFinished
(
index
,
text
)
{
if
(
text
.
length
===
0
)
{
// Remove.
var
default_value
=
values
.
model
.
get
(
index
).
$value
if
(
minValues
!=
null
&&
minValues
>=
values
.
model
.
count
)
{
var
model
=
values
.
model
var
model
=
values
.
model
var
defaultValue
=
model
.
get
(
index
).
$value
if
(
text
.
length
===
0
)
{
// No changes. It must exists at least n min values.
if
(
minValues
!=
null
&&
minValues
>=
model
.
count
)
{
// Unable to set property directly. Qt uses a cache of the value.
model
.
remove
(
index
)
model
.
insert
(
index
,
{
$isInvalid
:
false
,
$value
:
default
_v
alue
$value
:
default
V
alue
})
return
}
values
.
model
.
remove
(
index
)
model
.
remove
(
index
)
if
(
default_value
.
length
!==
0
)
{
listForm
.
removed
(
index
,
default_value
)
}
}
else
{
// Update.
var
default_value
=
values
.
model
.
get
(
index
).
$value
// If no changes, no signal.
if
(
text
!==
default_value
)
{
listForm
.
changed
(
index
,
default_value
,
text
)
if
(
defaultValue
.
length
!==
0
)
{
listForm
.
removed
(
index
,
defaultValue
)
}
}
else
if
(
text
!==
defaultValue
)
{
// Update changes.
listForm
.
changed
(
index
,
defaultValue
,
text
)
}
addButton
.
enabled
=
true
}
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
spacing
:
0
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
// Title area.
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
RowLayout
{
Layout.alignment
:
Qt
.
AlignTop
...
...
@@ -100,8 +96,9 @@ RowLayout {
icon
:
'
add
'
iconSize
:
ListFormStyle
.
titleArea
.
iconSize
opacity
:
_edition
?
1
:
0
onClicked
:
_addValue
(
''
)
onClicked
:
_
edition
&&
_
addValue
(
''
)
}
Text
{
...
...
@@ -118,9 +115,9 @@ RowLayout {
}
}
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
// Placeholder.
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
Text
{
id
:
placeholder
...
...
@@ -135,7 +132,7 @@ RowLayout {
}
padding
:
ListFormStyle
.
value
.
text
.
padding
visible
:
values
.
model
.
count
===
0
visible
:
values
.
model
.
count
===
0
&&
!
listForm
.
readOnly
verticalAlignment
:
Text
.
AlignVCenter
MouseArea
{
...
...
@@ -144,9 +141,9 @@ RowLayout {
}
}
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
// Values.
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
ListView
{
id
:
values
...
...
@@ -165,6 +162,7 @@ RowLayout {
inputMethodHints
:
listForm
.
inputMethodHints
isInvalid
:
$isInvalid
readOnly
:
listForm
.
readOnly
text
:
$value
height
:
ListFormStyle
.
lineHeight
...
...
@@ -190,16 +188,14 @@ RowLayout {
model
:
ListModel
{}
// ---------------------------------------------------------------
// ---------------------------------------------------------------
----------
// Init values.
// ---------------------------------------------------------------
// ---------------------------------------------------------------
----------
Component
.
onCompleted
:
{
if
(
!
defaultData
)
{
return
if
(
defaultData
)
{
setData
(
defaultData
)
}
setData
(
defaultData
)
}
}
}
tests/ui/modules/Common/Form/TextButtonA.qml
View file @
d308d0a3
import
Common
.
Styles
1.0
// ===================================================================
// ===================================================================
==========
AbstractTextButton
{
colorDisabled
:
TextButtonAStyle
.
backgroundColor
.
disabled
colorHovered
:
TextButtonAStyle
.
backgroundColor
.
hovered
colorNormal
:
TextButtonAStyle
.
backgroundColor
.
normal
colorPressed
:
TextButtonAStyle
.
backgroundColor
.
pressed
textColorDisabled
:
TextButtonAStyle
.
textColor
.
disabled
textColorHovered
:
TextButtonAStyle
.
textColor
.
hovered
textColorNormal
:
TextButtonAStyle
.
textColor
.
normal
textColorPressed
:
TextButtonAStyle
.
textColor
.
pressed
...
...
tests/ui/modules/Common/Form/TextButtonB.qml
View file @
d308d0a3
import
Common
.
Styles
1.0
// ===================================================================
// ===================================================================
==========
AbstractTextButton
{
colorDisabled
:
TextButtonBStyle
.
backgroundColor
.
disabled
colorHovered
:
TextButtonBStyle
.
backgroundColor
.
hovered
colorNormal
:
TextButtonBStyle
.
backgroundColor
.
normal
colorPressed
:
TextButtonBStyle
.
backgroundColor
.
pressed
textColorDisabled
:
TextButtonBStyle
.
textColor
.
disabled
textColorHovered
:
TextButtonBStyle
.
textColor
.
hovered
textColorNormal
:
TextButtonBStyle
.
textColor
.
normal
textColorPressed
:
TextButtonBStyle
.
textColor
.
pressed
...
...
tests/ui/modules/Common/Styles/Form/TextButtonAStyle.qml
View file @
d308d0a3
...
...
@@ -3,16 +3,18 @@ import QtQuick 2.7
import
Common
1.0
// ===================================================================
// ===================================================================
==========
QtObject
{
property
QtObject
backgroundColor
:
QtObject
{
property
color
disabled
:
Colors
.
o
property
color
hovered
:
Colors
.
o
property
color
normal
:
Colors
.
j
property
color
pressed
:
Colors
.
i
}
property
QtObject
textColor
:
QtObject
{
property
color
disabled
:
Colors
.
k
property
color
hovered
:
Colors
.
k
property
color
normal
:
Colors
.
k
property
color
pressed
:
Colors
.
k
...
...
tests/ui/modules/Common/Styles/Form/TextButtonBStyle.qml
View file @
d308d0a3
...
...
@@ -3,16 +3,18 @@ import QtQuick 2.7
import
Common
1.0
// ===================================================================
// ===================================================================
==========
QtObject
{
property
QtObject
backgroundColor
:
QtObject
{
property
color
disabled
:
Colors
.
i30
property
color
hovered
:
Colors
.
s
property
color
normal
:
Colors
.
i
property
color
pressed
:
Colors
.
t
}
property
QtObject
textColor
:
QtObject
{
property
color
disabled
:
Colors
.
k
property
color
hovered
:
Colors
.
k
property
color
normal
:
Colors
.
k
property
color
pressed
:
Colors
.
k
...
...
tests/ui/views/App/MainWindow/ContactEdit.qml
View file @
d308d0a3
...
...
@@ -5,22 +5,45 @@ import QtQuick.Layouts 1.3
import
Common
1.0
import
Linphone
1.0
import
LinphoneUtils
1.0
import
Utils
1.0
import
App
.
Styles
1.0
// ===================================================================
// ===================================================================
==========
ColumnLayout
{
id
:
contactEdit
property
string
sipAddress
:
''
property
string
sipAddress
property
bool
_edition
:
false
property
var
_contact
property
var
_vcard
// -----------------------------------------------------------------
// ---------------------------------------------------------------------------
function
_editContact
()
{
_contact
.
startEdit
()
_edition
=
true
}
function
_save
()
{
if
(
_contact
)
{
_contact
.
endEdit
()
_edition
=
false
}
else
{
_contact
=
ContactsListModel
.
addContact
(
_vcard
)
}
}
function
_cancel
()
{
if
(
_contact
)
{
_contact
.
abortEdit
()
_edition
=
false
}
else
{
window
.
setView
(
'
Contacts
'
)
}
}
function
_removeContact
()
{
Utils
.
openConfirmDialog
(
window
,
{
...
...
@@ -46,45 +69,55 @@ ColumnLayout {
usernameInput
.
text
=
_vcard
.
username
}
function
_handleSipAddressChanged
(
index
,
default
_value
,
new_v
alue
)
{
if
(
!
Utils
.
startsWith
(
new
_v
alue
,
'
sip:
'
))
{
new
_value
=
'
sip:
'
+
new_v
alue
function
_handleSipAddressChanged
(
index
,
default
Value
,
newV
alue
)
{
if
(
!
Utils
.
startsWith
(
new
V
alue
,
'
sip:
'
))
{
new
Value
=
'
sip:
'
+
newV
alue
if
(
new
_value
===
default_v
alue
)
{
if
(
new
Value
===
defaultV
alue
)
{
return
}
}
var
so_far_so_good
=
(
default
_v
alue
.
length
===
0
)
?
_vcard
.
addSipAddress
(
new
_v
alue
)
:
_vcard
.
updateSipAddress
(
default
_value
,
new_v
alue
)
var
so_far_so_good
=
(
default
V
alue
.
length
===
0
)
?
_vcard
.
addSipAddress
(
new
V
alue
)
:
_vcard
.
updateSipAddress
(
default
Value
,
newV
alue
)
addresses
.
setInvalid
(
index
,
!
so_far_so_good
)
}
function
_handleUrlChanged
(
index
,
default
_value
,
new_v
alue
)
{
var
url
=
Utils
.
extractFirstUri
(
new
_v
alue
)
if
(
url
===
default
_v
alue
)
{
function
_handleUrlChanged
(
index
,
default
Value
,
newV
alue
)
{
var
url
=
Utils
.
extractFirstUri
(
new
V
alue
)
if
(
url
===
default
V
alue
)
{
return
}
var
so_far_so_good
=
(
default
_v
alue
.
length
===
0
)
?
url
&&
_vcard
.
addUrl
(
new
_v
alue
)
:
url
&&
_vcard
.
updateUrl
(
default
_value
,
new_v
alue
)
var
so_far_so_good
=
(
default
V
alue
.
length
===
0
)
?
url
&&
_vcard
.
addUrl
(
new
V
alue
)
:
url
&&
_vcard
.
updateUrl
(
default
Value
,
newV
alue
)
urls
.
setInvalid
(
index
,
!
so_far_so_good
)
}
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
spacing
:
0
Component.onCompleted
:
{
_contact
=
ContactsListModel
.
mapSipAddressToContact
(
sipAddress
)
_vcard
=
_contact
.
vcard
if
(
!
_contact
)
{
_vcard
=
CoreManager
.
createDetachedVcardModel
()
_edition
=
true
}
else
{
_vcard
=
_contact
.
vcard
}
}
// -----------------------------------------------------------------
Component.onDestruction
:
{
// TODO: Remove photo if contact not created.
}
// ---------------------------------------------------------------------------
FileDialog
{
id
:
avatarChooser
...
...
@@ -95,9 +128,9 @@ ColumnLayout {
onAccepted
:
_setAvatar
(
fileUrls
[
0
])
}
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
// Info bar.
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
Rectangle
{
Layout.fillWidth
:
true
...
...
@@ -124,7 +157,7 @@ ColumnLayout {
anchors.fill
:
parent
image
:
_vcard
.
avatar
username
:
LinphoneUtils
.
getContactUsername
(
_contact
)
||
'
John Doe
'
username
:
_vcard
.
username
visible
:
isLoaded
()
&&
!
parent
.
hovered
}
}
...
...
@@ -155,22 +188,30 @@ ColumnLayout {
ActionButton
{
icon
:
'
history
'
onClicked
:
window
.
setView
(
'
Conversation
'
,
{
sipAddress
:
contactEdit
.
sipAddress
})
}
ActionButton
{
icon
:
'
edit
'
visible
:
!
_edition
onClicked
:
_editContact
()
}
ActionButton
{
icon
:
'
delete
'
onClicked
:
_removeContact
()
}
}
}
}
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
// Info list.
// -----------------------------------------------------------------
// -----------------------------------------------------------------
----------
Flickable
{
id
:
flick
...
...
@@ -197,12 +238,13 @@ ColumnLayout {
Layout.rightMargin
:
ContactEditStyle
.
values
.
rightMargin
Layout.topMargin
:
ContactEditStyle
.
values
.
topMargin
defaultData
:
_vcard
.
sipAddresses
minValues
:
1
defaultData
:
_vcard
.
sipAddresses
minValues
:
_contact
?
1
:
0
placeholder
:
qsTr
(
'
sipAccountsInput
'
)
readOnly
:
!
_edition
title
:
qsTr
(
'
sipAccounts
'
)
onChanged
:
_handleSipAddressChanged
(
index
,
default
_value
,
new_v
alue
)
onChanged
:
_handleSipAddressChanged
(
index
,
default
Value
,
newV
alue
)
onRemoved
:
_vcard
.
removeSipAddress
(
value
)
}
...
...
@@ -220,11 +262,12 @@ ColumnLayout {
defaultData
:
_vcard
.
companies
placeholder
:
qsTr
(
'
companiesInput
'
)
readOnly
:
!
_edition
title
:
qsTr
(
'
companies
'
)
onChanged
:
default
_v
alue
.
length
===
0
?
_vcard
.
addCompany
(
new
_v
alue
)
:
_vcard
.
updateCompany
(
default
_value
,
new_v
alue
)
onChanged
:
default
V
alue
.
length
===
0
?
_vcard
.
addCompany
(
new
V
alue
)
:
_vcard
.
updateCompany
(
default
Value
,
newV
alue
)
onRemoved
:
_vcard
.
removeCompany
(
value
)
}
...
...
@@ -243,11 +286,12 @@ ColumnLayout {
defaultData
:
_vcard
.
emails
inputMethodHints
:
Qt
.
ImhEmailCharactersOnly
placeholder
:
qsTr
(
'
emailsInput
'
)
readOnly
:
!
_edition
title
:
qsTr
(
'
emails
'
)
onChanged
:
default
_v
alue
.
length
===
0
?
_vcard
.
addEmail
(
new
_v
alue
)
:
_vcard
.
updateEmail
(
default
_value
,
new_v
alue
)
onChanged
:
default
V
alue
.
length
===
0
?
_vcard
.
addEmail
(
new
V
alue
)
:
_vcard
.
updateEmail
(
default
Value
,
newV
alue
)
onRemoved
:
_vcard
.
removeEmail
(
value
)
}
...
...
@@ -266,9 +310,10 @@ ColumnLayout {
defaultData
:
_vcard
.
urls
inputMethodHints
:
Qt
.
ImhUrlCharactersOnly
placeholder
:
qsTr
(
'
webSitesInput
'
)
readOnly
:
!
_edition
title
:
qsTr
(
'
webSites
'
)
onChanged
:
_handleUrlChanged
(
index
,
default
_value
,
new_v
alue
)
onChanged
:
_handleUrlChanged
(
index
,
default
Value
,
newV
alue
)
onRemoved
:
_vcard
.
removeUrl
(
value
)
}
...
...
@@ -278,20 +323,21 @@ ColumnLayout {
color
:
ContactEditStyle
.
values
.
separator
.
color
}
Loader
{
Row
{
Layout.alignment
:
Qt
.
AlignHCenter
Layout.topMargin
:
ContactEditStyle
.
buttons
.
topMargin
spacing
:
ContactEditStyle
.
buttons
.
spacing
visible
:
_edition
sourceComponent
:
Row
{
spacing
:
ContactEditStyle
.
buttons
.
spacing
TextButtonB
{
text
:
qsTr
(
'
save
'
)
}
TextButtonB
{
enabled
:
_vcard
.
sipAddresses
.
length
>
0
text
:
qsTr
(
'
save
'
)
onClicked
:
_save
()
}
TextButtonA
{
text
:
qsTr
(
'
cancel
'
)
}
TextButtonA
{
text
:
qsTr
(
'
cancel
'
)
onClicked
:
_cancel
()
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment