Merge branch 'feature/dev_group_chat_integration' [Switch submodule branch]

This commit is contained in:
Ronan Abhamon 2018-08-30 12:12:54 +02:00
commit 37f41b8432
138 changed files with 1818 additions and 148931 deletions

3
.gitmodules vendored
View file

@ -110,3 +110,6 @@
[submodule "submodules/externals/minizip"]
path = submodules/externals/minizip
url = https://gitlab.linphone.org/BC/public/external/minizip.git
[submodule "submodules/externals/sqlite3"]
path = submodules/externals/sqlite3
url = https://gitlab.linphone.org/BC/public/external/sqlite3.git

View file

@ -1,5 +1,13 @@
# Changelog
## 4.2.0 - Unknown
### Features
- Timeline uses current proxy config info.
- Display only unread chat message count of active proxy list.
- Display unread chat messages count in `Manage Accounts` dialog and in `Main Window`.
## 4.1.0 - 2017-07-19
### Features

View file

@ -142,7 +142,7 @@ set(SOURCES
src/components/contacts/ContactsListProxyModel.cpp
src/components/core/CoreHandlers.cpp
src/components/core/CoreManager.cpp
src/components/core/messages-count-notifier/AbstractMessagesCountNotifier.cpp
src/components/core/messages-count-notifier/AbstractMessageCountNotifier.cpp
src/components/file/FileDownloader.cpp
src/components/file/FileExtractor.cpp
src/components/notifier/Notifier.cpp
@ -200,7 +200,7 @@ set(HEADERS
src/components/contacts/ContactsListProxyModel.hpp
src/components/core/CoreHandlers.hpp
src/components/core/CoreManager.hpp
src/components/core/messages-count-notifier/AbstractMessagesCountNotifier.hpp
src/components/core/messages-count-notifier/AbstractMessageCountNotifier.hpp
src/components/file/FileDownloader.hpp
src/components/file/FileExtractor.hpp
src/components/notifier/Notifier.hpp
@ -230,37 +230,37 @@ set(MAIN_FILE src/app/main.cpp)
if (APPLE)
list(APPEND SOURCES
src/app/single-application/SingleApplication.cpp
src/components/core/messages-count-notifier/MessagesCountNotifierMacOs.m
src/components/core/messages-count-notifier/MessageCountNotifierMacOs.m
src/components/other/desktop-tools/DesktopToolsMacOs.cpp
src/components/other/desktop-tools/screen-saver/ScreenSaverMacOs.m
)
list(APPEND HEADERS
src/app/single-application/SingleApplicationPrivate.hpp
src/components/core/messages-count-notifier/MessagesCountNotifierMacOs.hpp
src/components/core/messages-count-notifier/MessageCountNotifierMacOs.hpp
src/components/other/desktop-tools/DesktopToolsMacOs.hpp
)
elseif (WIN32)
list(APPEND SOURCES
src/app/single-application/SingleApplication.cpp
src/components/core/messages-count-notifier/MessagesCountNotifierSystemTrayIcon.cpp
src/components/core/messages-count-notifier/MessageCountNotifierSystemTrayIcon.cpp
src/components/other/desktop-tools/DesktopToolsWindows.cpp
)
list(APPEND HEADERS
src/app/single-application/SingleApplicationPrivate.hpp
src/components/core/messages-count-notifier/MessagesCountNotifierSystemTrayIcon.hpp
src/components/core/messages-count-notifier/MessageCountNotifierSystemTrayIcon.hpp
src/components/other/desktop-tools/DesktopToolsWindows.hpp
)
else ()
list(APPEND SOURCES
src/app/single-application/SingleApplicationDBus.cpp
src/components/core/messages-count-notifier/MessagesCountNotifierSystemTrayIcon.cpp
src/components/core/messages-count-notifier/MessageCountNotifierSystemTrayIcon.cpp
src/components/other/desktop-tools/DesktopToolsLinux.cpp
src/components/other/desktop-tools/screen-saver/ScreenSaverDBus.cpp
src/components/other/desktop-tools/screen-saver/ScreenSaverXdg.cpp
)
list(APPEND HEADERS
src/app/single-application/SingleApplicationDBusPrivate.hpp
src/components/core/messages-count-notifier/MessagesCountNotifierSystemTrayIcon.hpp
src/components/core/messages-count-notifier/MessageCountNotifierSystemTrayIcon.hpp
src/components/other/desktop-tools/DesktopToolsLinux.hpp
src/components/other/desktop-tools/screen-saver/ScreenSaverDBus.hpp
src/components/other/desktop-tools/screen-saver/ScreenSaverXdg.hpp

View file

@ -26,7 +26,7 @@ Here are the general instructions to build linphone for desktop. The specific in
1. Prepare the build in a terminal by running the following command in the current directory:
./prepare.py
./prepare.py -DENABLE_DOC=OFF
2. Build the project in a terminal with:
@ -43,7 +43,7 @@ Here are the general instructions to build linphone for desktop. The specific in
3. Open a Windows command line (cmd.exe) in the current directory and run:
python prepare.py -G "Visual Studio 14 2015"
python prepare.py -G "Visual Studio 14 2015" -DENABLE_DOC=OFF
4. Open the generated Visual Studio solution `Project.sln.lnk` and build it. Check if the `Release` option is selected in Visual Studio. (With `Win32`!)

View file

@ -28,7 +28,7 @@
</section>
<section name="assistant">
<entry name="domain" overwrite="true">sip.linphone.org</entry>
<entry name="password_max_length" overwrite="true">34</entry>
<entry name="password_max_length" overwrite="true">-1</entry>
<entry name="password_min_length" overwrite="true">1</entry>
<entry name="username_length" overwrite="true">-1</entry>
<entry name="username_max_length" overwrite="true">64</entry>

View file

@ -1,12 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title>auto_answer_active</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="auto_answer_active" stroke="#828282">
<path d="M0.797365543,2.49263511 C-0.109836641,5.04855335 1.161449,8.70129794 3.21892643,10.7501941 L3.26206927,10.7928576 C5.31909573,12.8413047 8.98804084,14.1072881 11.5537619,13.2038696 L13.5,10.6632204 L10.8490455,8.02362183 L8.42387683,10.0659313 L6.20750748,7.85910537 L6.16496594,7.81644186 L3.94889724,5.60961588 L5.99930947,3.19366387 L3.34940721,0.554364667 L0.797365543,2.49263511 L0.797365543,2.49263511 Z"></path>
</g>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg12"
sodipodi:docname="auto_answer.svg"
inkscape:version="0.92.2 2405546, 2018-03-11">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>auto_answer_active</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="985"
id="namedview14"
showgrid="false"
inkscape:zoom="2.1071429"
inkscape:cx="14.372881"
inkscape:cy="11.180255"
inkscape:window-x="0"
inkscape:window-y="35"
inkscape:window-maximized="1"
inkscape:current-layer="svg12" />
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title
id="title2">auto_answer_active</title>
<desc
id="desc4">Created with Sketch.</desc>
<defs
id="defs6" />
<g
id="Symbols"
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
transform="translate(1,1)">
<g
id="auto_answer_active"
style="stroke:#fe5e00"
class="color-i-stroke">
<path
d="M 0.79736554,2.4926351 C -0.10983664,5.0485533 1.161449,8.7012979 3.2189264,10.750194 l 0.043143,0.04266 c 2.0570264,2.048447 5.7259715,3.31443 8.2916926,2.411012 L 13.5,10.66322 10.849046,8.0236218 8.4238768,10.065931 6.2075075,7.8591054 6.1649659,7.8164419 3.9488972,5.6096159 5.9993095,3.1936639 3.3494072,0.55436467 Z"
id="path8"
inkscape:connector-curvature="0" />
</g>
</svg>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1,013 B

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -1,13 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title>call_lost</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
<g id="call_lost" class="color-error-stroke" stroke="#FF0000" stroke-width="2">
<path d="M12.9852814,5.74407768 L-1.15685425,5.74407768" id="Line" transform="translate(6.266032, 5.768485) rotate(-45.000000) translate(-6.266032, -5.768485) "></path>
<path d="M11,11 L1,1" id="Line"></path>
</g>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="18"
height="18"
viewBox="0 0 18 18"
version="1.1"
id="svg13"
sodipodi:docname="declined_incoming_call.svg"
inkscape:version="0.92.2 2405546, 2018-03-11">
<metadata
id="metadata17">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>call_lost</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="985"
id="namedview15"
showgrid="false"
inkscape:zoom="6.9532167"
inkscape:cx="1.925277"
inkscape:cy="3.533194"
inkscape:window-x="0"
inkscape:window-y="35"
inkscape:window-maximized="1"
inkscape:current-layer="svg13" />
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title
id="title2">call_lost</title>
<desc
id="desc4">Created with Sketch.</desc>
<defs
id="defs6" />
<g
id="Symbols"
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round"
transform="translate(3,3)">
<g
id="call_lost"
class="color-error-stroke"
style="stroke:#ff0000;stroke-width:2">
<path
d="M 12.985281,5.7440777 H -1.1568543"
id="Line"
transform="rotate(-45,6.266032,5.768485)"
inkscape:connector-curvature="0" />
<path
d="M 11,11 1,1"
id="path9"
inkscape:connector-curvature="0" />
</g>
</svg>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 808 B

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -1,13 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title>call_lost</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
<g id="call_lost" class="color-error-stroke" stroke="#FF0000" stroke-width="2">
<path d="M12.9852814,5.74407768 L-1.15685425,5.74407768" id="Line" transform="translate(6.266032, 5.768485) rotate(-45.000000) translate(-6.266032, -5.768485) "></path>
<path d="M11,11 L1,1" id="Line"></path>
</g>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="18"
height="18"
viewBox="0 0 18 18"
version="1.1"
id="svg13"
sodipodi:docname="declined_incoming_call.svg"
inkscape:version="0.92.2 2405546, 2018-03-11">
<metadata
id="metadata17">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>call_lost</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="985"
id="namedview15"
showgrid="false"
inkscape:zoom="6.9532167"
inkscape:cx="1.925277"
inkscape:cy="3.533194"
inkscape:window-x="0"
inkscape:window-y="35"
inkscape:window-maximized="1"
inkscape:current-layer="svg13" />
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title
id="title2">call_lost</title>
<desc
id="desc4">Created with Sketch.</desc>
<defs
id="defs6" />
<g
id="Symbols"
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round"
transform="translate(3,3)">
<g
id="call_lost"
class="color-error-stroke"
style="stroke:#ff0000;stroke-width:2">
<path
d="M 12.985281,5.7440777 H -1.1568543"
id="Line"
transform="rotate(-45,6.266032,5.768485)"
inkscape:connector-curvature="0" />
<path
d="M 11,11 1,1"
id="path9"
inkscape:connector-curvature="0" />
</g>
</svg>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 808 B

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -1,13 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title>call_lost</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
<g id="call_lost" class="color-error-stroke" stroke="#FF0000" stroke-width="2">
<path d="M12.9852814,5.74407768 L-1.15685425,5.74407768" id="Line" transform="translate(6.266032, 5.768485) rotate(-45.000000) translate(-6.266032, -5.768485) "></path>
<path d="M11,11 L1,1" id="Line"></path>
</g>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="18"
height="18"
viewBox="0 0 18 18"
version="1.1"
id="svg13"
sodipodi:docname="declined_incoming_call.svg"
inkscape:version="0.92.2 2405546, 2018-03-11">
<metadata
id="metadata17">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>call_lost</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="985"
id="namedview15"
showgrid="false"
inkscape:zoom="6.9532167"
inkscape:cx="1.925277"
inkscape:cy="3.533194"
inkscape:window-x="0"
inkscape:window-y="35"
inkscape:window-maximized="1"
inkscape:current-layer="svg13" />
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title
id="title2">call_lost</title>
<desc
id="desc4">Created with Sketch.</desc>
<defs
id="defs6" />
<g
id="Symbols"
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round"
transform="translate(3,3)">
<g
id="call_lost"
class="color-error-stroke"
style="stroke:#ff0000;stroke-width:2">
<path
d="M 12.985281,5.7440777 H -1.1568543"
id="Line"
transform="rotate(-45,6.266032,5.768485)"
inkscape:connector-curvature="0" />
<path
d="M 11,11 1,1"
id="path9"
inkscape:connector-curvature="0" />
</g>
</svg>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 808 B

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -1,13 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title>call_lost</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
<g id="call_lost" class="color-error-stroke" stroke="#FF0000" stroke-width="2">
<path d="M12.9852814,5.74407768 L-1.15685425,5.74407768" id="Line" transform="translate(6.266032, 5.768485) rotate(-45.000000) translate(-6.266032, -5.768485) "></path>
<path d="M11,11 L1,1" id="Line"></path>
</g>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="18"
height="18"
viewBox="0 0 18 18"
version="1.1"
id="svg13"
sodipodi:docname="declined_incoming_call.svg"
inkscape:version="0.92.2 2405546, 2018-03-11">
<metadata
id="metadata17">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>call_lost</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="985"
id="namedview15"
showgrid="false"
inkscape:zoom="6.9532167"
inkscape:cx="1.925277"
inkscape:cy="3.533194"
inkscape:window-x="0"
inkscape:window-y="35"
inkscape:window-maximized="1"
inkscape:current-layer="svg13" />
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title
id="title2">call_lost</title>
<desc
id="desc4">Created with Sketch.</desc>
<defs
id="defs6" />
<g
id="Symbols"
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round"
transform="translate(3,3)">
<g
id="call_lost"
class="color-error-stroke"
style="stroke:#ff0000;stroke-width:2">
<path
d="M 12.985281,5.7440777 H -1.1568543"
id="Line"
transform="rotate(-45,6.266032,5.768485)"
inkscape:connector-curvature="0" />
<path
d="M 11,11 1,1"
id="path9"
inkscape:connector-curvature="0" />
</g>
</svg>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 808 B

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -305,7 +305,7 @@
</message>
<message>
<source>iceStateInProgress</source>
<translation type="unfinished"></translation>
<translation>Pågående</translation>
</message>
<message>
<source>iceStateReflexiveConnection</source>

View file

@ -78,7 +78,7 @@
</message>
<message>
<source>restore</source>
<translation type="unfinished"></translation>
<translation>Kurtar</translation>
</message>
<message>
<source>quit</source>
@ -933,7 +933,10 @@ Sunucu url&apos;si yapılandırılmadı.</translation>
</message>
<message>
<source>forcedMessage</source>
<translation type="unfinished"></translation>
<translation>Uygulamayı bilgisayarınıza indirin ve kullanıcıları ücretsiz olarak aramaya ve konuşmaya başlayın.
Buraya tıklayın: &lt;a href=&quot;%1&quot;&gt;%1&lt;/a&gt;
</translation>
</message>
</context>
<context>
@ -1013,7 +1016,7 @@ arkadaşınızın SIP adresini veya kullanıcı adını girin.</translation>
<name>Notifier</name>
<message>
<source>newVersionAvailable</source>
<translation type="unfinished"></translation>
<translation>Yeni sürüm (%1) var!</translation>
</message>
<message>
<source>newFileMessage</source>
@ -1152,7 +1155,7 @@ arkadaşınızın SIP adresini veya kullanıcı adını girin.</translation>
</message>
<message>
<source>showAudioCodecsLabel</source>
<translation type="unfinished"></translation>
<translation>Ses çözücüleri göster</translation>
</message>
</context>
<context>
@ -1223,39 +1226,39 @@ arkadaşınızın SIP adresini veya kullanıcı adını girin.</translation>
</message>
<message>
<source>conferenceEnabledLabel</source>
<translation type="unfinished"></translation>
<translation>Toplantıyı etkinleştir</translation>
</message>
<message>
<source>contactsTitle</source>
<translation type="unfinished"></translation>
<translation>Kişiler</translation>
</message>
<message>
<source>contactsEnabledLabel</source>
<translation type="unfinished"></translation>
<translation>Kişileri etkinleştir</translation>
</message>
<message>
<source>muteMicrophoneEnabledLabel</source>
<translation type="unfinished"></translation>
<translation>Mikrofonu kısmayı etkinleştir</translation>
</message>
<message>
<source>outgoingCallsEnabledLabel</source>
<translation type="unfinished"></translation>
<translation>Giden çağrıları ektinleştir</translation>
</message>
<message>
<source>showTelKeypadAutomaticallyLabel</source>
<translation type="unfinished"></translation>
<translation>Telefon numara takımını kendiliğinden göster</translation>
</message>
<message>
<source>automaticallyRecordCallsLabel</source>
<translation type="unfinished"></translation>
<translation>Çağrıları kendiliğinden kaydet</translation>
</message>
<message>
<source>keepCallsWindowInBackgroundLabel</source>
<translation type="unfinished"></translation>
<translation>Çağrı pencerelerini arka planda tut</translation>
</message>
<message>
<source>callPauseEnabledLabel</source>
<translation type="unfinished"></translation>
<translation>Çağrı duraklatma etkin</translation>
</message>
</context>
<context>
@ -1378,11 +1381,11 @@ arkadaşınızın SIP adresini veya kullanıcı adını girin.</translation>
</message>
<message>
<source>showNetworkSettingsLabel</source>
<translation type="unfinished"></translation>
<translation> ayarlarını göster</translation>
</message>
<message>
<source>generalTitle</source>
<translation type="unfinished"></translation>
<translation>Genel</translation>
</message>
</context>
<context>
@ -1437,23 +1440,23 @@ arkadaşınızın SIP adresini veya kullanıcı adını girin.</translation>
</message>
<message>
<source>createAppSipAccountEnabledLabel</source>
<translation type="unfinished"></translation>
<translation>Hesap oluşturmayı etkinleştir</translation>
</message>
<message>
<source>useAppSipAccountEnabledLabel</source>
<translation type="unfinished"></translation>
<translation>Hesap kullanımını etkinleştir</translation>
</message>
<message>
<source>useOtherSipAccountEnabledLabel</source>
<translation type="unfinished"></translation>
<translation>Genel hesap kullanımını etkinleştir</translation>
</message>
<message>
<source>fetchRemoteConfigurationEnabledLabel</source>
<translation type="unfinished"></translation>
<translation>Yapılandırma almayı etkinleştir</translation>
</message>
<message>
<source>assistantSupportsPhoneNumbersLabel</source>
<translation type="unfinished"></translation>
<translation>Telefon numaralarını destekler</translation>
</message>
</context>
<context>
@ -1559,7 +1562,7 @@ arkadaşınızın SIP adresini veya kullanıcı adını girin.</translation>
</message>
<message>
<source>savedCallsLabel</source>
<translation type="unfinished"></translation>
<translation>Kaydedilen çağrılar klasörü</translation>
</message>
<message>
<source>languagesTitle</source>
@ -1646,7 +1649,7 @@ arkadaşınızın SIP adresini veya kullanıcı adını girin.</translation>
</message>
<message>
<source>showVideoCodecsLabel</source>
<translation type="unfinished"></translation>
<translation>Görüntü çözücüleri göster</translation>
</message>
</context>
<context>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -3,18 +3,18 @@
<name>About</name>
<message>
<source>ok</source>
<translation type="unfinished"/>
<translation></translation>
</message>
</context>
<context>
<name>ActivateAppSipAccountWithEmail</name>
<message>
<source>activateAppSipAccount</source>
<translation type="unfinished"/>
<translation> %1 </translation>
</message>
<message>
<source>confirmAction</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>activationSteps</source>
@ -25,11 +25,11 @@
<name>ActivateAppSipAccountWithPhoneNumber</name>
<message>
<source>activateAppSipAccount</source>
<translation type="unfinished"/>
<translation> %1 </translation>
</message>
<message>
<source>confirmAction</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>activationSteps</source>
@ -56,15 +56,15 @@
</message>
<message>
<source>commandLineOptionConfigArg</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>commandLineOptionHelp</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>commandLineOptionVersion</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>commandLineOptionCliHelp</source>
@ -1323,10 +1323,6 @@
<source>enabledPortHeader</source>
<translation type="unfinished"/>
</message>
<message>
<source>enableTlsLabel</source>
<translation type="unfinished"/>
</message>
<message>
<source>dscpFieldsTitle</source>
<translation type="unfinished"/>

View file

@ -22,7 +22,6 @@
lcb_define_target("linphoneqt" "linphone" "ms2plugins")
lcb_blacklist_dependencies("libxsd" "soci") # linphone do not need them for the moment.
if (NOT WIN32 AND NOT APPLE)
lcb_blacklist_dependencies("turbo-jpeg") # turbo-jpeg is already provided by Qt5 so do not build it.

View file

@ -24,6 +24,7 @@ lcb_external_source_paths("..")
lcb_dependencies("linphone" "ms2plugins" "minizip")
lcb_groupable(YES)
lcb_sanitizable(YES)
lcb_package_source(YES)
lcb_spec_file("linphoneqt.spec")

View file

@ -216,6 +216,7 @@
<file>ui/modules/Common/Form/CheckBoxText.qml</file>
<file>ui/modules/Common/Form/ComboBox.js</file>
<file>ui/modules/Common/Form/ComboBox.qml</file>
<file>ui/modules/Common/Form/CommonItemDelegate.qml</file>
<file>ui/modules/Common/Form/DroppableTextArea.qml</file>
<file>ui/modules/Common/Form/Fields/HexField.qml</file>
<file>ui/modules/Common/Form/Fields/NumericField.qml</file>
@ -226,6 +227,8 @@
<file>ui/modules/Common/Form/Fields/TextField.qml</file>
<file>ui/modules/Common/Form/ListForm.js</file>
<file>ui/modules/Common/Form/ListForm.qml</file>
<file>ui/modules/Common/Form/ListItemSelector.js</file>
<file>ui/modules/Common/Form/ListItemSelector.qml</file>
<file>ui/modules/Common/Form/Placements/FormEmptyLine.qml</file>
<file>ui/modules/Common/Form/Placements/FormGroup.qml</file>
<file>ui/modules/Common/Form/Placements/FormHGroup.qml</file>
@ -273,6 +276,7 @@
<file>ui/modules/Common/Styles/Form/Buttons/TextButtonBStyle.qml</file>
<file>ui/modules/Common/Styles/Form/CheckBoxTextStyle.qml</file>
<file>ui/modules/Common/Styles/Form/ComboBoxStyle.qml</file>
<file>ui/modules/Common/Styles/Form/CommonItemDelegateStyle.qml</file>
<file>ui/modules/Common/Styles/Form/DroppableTextAreaStyle.qml</file>
<file>ui/modules/Common/Styles/Form/Fields/NumericFieldStyle.qml</file>
<file>ui/modules/Common/Styles/Form/Fields/TextAreaFieldStyle.qml</file>
@ -331,10 +335,11 @@
<file>ui/modules/Linphone/Codecs/CodecsViewer.qml</file>
<file>ui/modules/Linphone/Contact/Avatar.qml</file>
<file>ui/modules/Linphone/Contact/ContactDescription.qml</file>
<file>ui/modules/Linphone/Contact/ContactMessageCounter.qml</file>
<file>ui/modules/Linphone/Contact/Contact.qml</file>
<file>ui/modules/Linphone/Contact/MessagesCounter.qml</file>
<file>ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml</file>
<file>ui/modules/Linphone/Menus/SipAddressesMenu.qml</file>
<file>ui/modules/Linphone/Misc/MessageCounter.qml</file>
<file>ui/modules/Linphone/Notifications/NotificationBasic.qml</file>
<file>ui/modules/Linphone/Notifications/NotificationNewVersionAvailable.qml</file>
<file>ui/modules/Linphone/Notifications/Notification.qml</file>
@ -357,10 +362,11 @@
<file>ui/modules/Linphone/Styles/Codecs/CodecsViewerStyle.qml</file>
<file>ui/modules/Linphone/Styles/Contact/AvatarStyle.qml</file>
<file>ui/modules/Linphone/Styles/Contact/ContactDescriptionStyle.qml</file>
<file>ui/modules/Linphone/Styles/Contact/ContactMessageCounterStyle.qml</file>
<file>ui/modules/Linphone/Styles/Contact/ContactStyle.qml</file>
<file>ui/modules/Linphone/Styles/Contact/MessagesCounterStyle.qml</file>
<file>ui/modules/Linphone/Styles/Dialog/OnlineInstallerDialogStyle.qml</file>
<file>ui/modules/Linphone/Styles/Menus/SipAddressesMenuStyle.qml</file>
<file>ui/modules/Linphone/Styles/Misc/MessageCounterStyle.qml</file>
<file>ui/modules/Linphone/Styles/Notifications/NotificationBasicStyle.qml</file>
<file>ui/modules/Linphone/Styles/Notifications/NotificationReceivedCallStyle.qml</file>
<file>ui/modules/Linphone/Styles/Notifications/NotificationReceivedFileMessageStyle.qml</file>
@ -420,6 +426,7 @@
<file>ui/views/App/Main/Dialogs/About.qml</file>
<file>ui/views/App/Main/Dialogs/AuthenticationRequest.js</file>
<file>ui/views/App/Main/Dialogs/AuthenticationRequest.qml</file>
<file>ui/views/App/Main/Dialogs/ManageAccount.js</file>
<file>ui/views/App/Main/Dialogs/ManageAccounts.qml</file>
<file>ui/views/App/Main/Home.qml</file>
<file>ui/views/App/Main/InviteFriends.qml</file>

View file

@ -106,17 +106,15 @@ static void cliInitiateConference (QHash<QString, QString> &args) {
address->clean();
const string sipAddress = address->asString();
shared_ptr<linphone::ProxyConfig> proxyConfig = core->getDefaultProxyConfig();
if (!proxyConfig) {
qWarning() << QStringLiteral("Not connected to a proxy config");
return;
}
const string identity = proxyConfig->getIdentityAddress()->asStringUriOnly();
if (sipAddress != identity) {
if (!proxyConfig->getIdentityAddress()->weakEqual(address)) {
qWarning() << QStringLiteral("Received different sip address from identity : `%1 != %2`.")
.arg(Utils::coreStringToAppString(identity))
.arg(Utils::coreStringToAppString(sipAddress));
.arg(Utils::coreStringToAppString(proxyConfig->getIdentityAddress()->asString()))
.arg(Utils::coreStringToAppString(address->asString()));
return;
}
}

View file

@ -87,22 +87,22 @@ private:
using LogLevel = linphone::LogLevel;
const char *format;
switch (level) {
case LogLevel::LogLevelDebug:
case LogLevel::Debug:
format = GREEN "[%s][Debug]" YELLOW "Core:%s: " RESET "%s\n";
break;
case LogLevel::LogLevelTrace:
case LogLevel::Trace:
format = BLUE "[%s][Trace]" YELLOW "Core:%s: " RESET "%s\n";
break;
case LogLevel::LogLevelMessage:
case LogLevel::Message:
format = BLUE "[%s][Info]" YELLOW "Core:%s: " RESET "%s\n";
break;
case LogLevel::LogLevelWarning:
case LogLevel::Warning:
format = RED "[%s][Warning]" YELLOW "Core:%s: " RESET "%s\n";
break;
case LogLevel::LogLevelError:
case LogLevel::Error:
format = RED "[%s][Error]" YELLOW "Core:%s: " RESET "%s\n";
break;
case LogLevel::LogLevelFatal:
case LogLevel::Fatal:
format = RED "[%s][Fatal]" YELLOW "Core:%s: " RESET "%s\n";
break;
}
@ -115,7 +115,7 @@ private:
message.c_str()
);
if (level == LogLevel::LogLevelFatal)
if (level == LogLevel::Fatal)
terminate();
};
@ -183,8 +183,8 @@ void Logger::log (QtMsgType type, const QMessageLogContext &context, const QStri
void Logger::enable (bool status) {
linphone::Core::enableLogCollection(
status
? linphone::LogCollectionStateEnabled
: linphone::LogCollectionStateDisabled
? linphone::LogCollectionState::Enabled
: linphone::LogCollectionState::Disabled
);
}
@ -201,7 +201,7 @@ void Logger::init (const shared_ptr<linphone::Config> &config) {
{
shared_ptr<linphone::LoggingService> loggingService = mInstance->mLoggingService = linphone::LoggingService::get();
loggingService->setLogLevel(linphone::LogLevel::LogLevelMessage);
loggingService->setLogLevel(linphone::LogLevel::Message);
loggingService->setListener(make_shared<LinphoneLogger>(mInstance));
}

View file

@ -52,15 +52,15 @@ private:
void onCreateAccount (
const shared_ptr<linphone::AccountCreator> &,
linphone::AccountCreatorStatus status,
linphone::AccountCreator::Status status,
const string &
) override {
if (status == linphone::AccountCreatorStatusAccountCreated)
if (status == linphone::AccountCreator::Status::AccountCreated)
emit mAssistant->createStatusChanged(QString(""));
else {
if (status == linphone::AccountCreatorStatusRequestFailed)
if (status == linphone::AccountCreator::Status::RequestFailed)
emit mAssistant->createStatusChanged(tr("requestFailed"));
else if (status == linphone::AccountCreatorStatusServerError)
else if (status == linphone::AccountCreator::Status::ServerError)
emit mAssistant->createStatusChanged(tr("cannotSendSms"));
else
emit mAssistant->createStatusChanged(tr("accountAlreadyExists"));
@ -69,14 +69,14 @@ private:
void onIsAccountExist (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
linphone::AccountCreator::Status status,
const string &
) override {
if (status == linphone::AccountCreatorStatusAccountExist || status == linphone::AccountCreatorStatusAccountExistWithAlias) {
if (status == linphone::AccountCreator::Status::AccountExist || status == linphone::AccountCreator::Status::AccountExistWithAlias) {
createProxyConfig(creator);
emit mAssistant->loginStatusChanged(QString(""));
} else {
if (status == linphone::AccountCreatorStatusRequestFailed)
if (status == linphone::AccountCreator::Status::RequestFailed)
emit mAssistant->loginStatusChanged(tr("requestFailed"));
else
emit mAssistant->loginStatusChanged(tr("loginWithUsernameFailed"));
@ -85,19 +85,19 @@ private:
void onActivateAccount (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
linphone::AccountCreator::Status status,
const string &
) override {
if (
status == linphone::AccountCreatorStatusAccountActivated ||
status == linphone::AccountCreatorStatusAccountAlreadyActivated
status == linphone::AccountCreator::Status::AccountActivated ||
status == linphone::AccountCreator::Status::AccountAlreadyActivated
) {
if (creator->getEmail().empty())
createProxyConfig(creator);
emit mAssistant->activateStatusChanged(QString(""));
} else {
if (status == linphone::AccountCreatorStatusRequestFailed)
if (status == linphone::AccountCreator::Status::RequestFailed)
emit mAssistant->activateStatusChanged(tr("requestFailed"));
else
emit mAssistant->activateStatusChanged(tr("smsActivationFailed"));
@ -106,14 +106,14 @@ private:
void onIsAccountActivated (
const shared_ptr<linphone::AccountCreator> &creator,
linphone::AccountCreatorStatus status,
linphone::AccountCreator::Status status,
const string &
) override {
if (status == linphone::AccountCreatorStatusAccountActivated) {
if (status == linphone::AccountCreator::Status::AccountActivated) {
createProxyConfig(creator);
emit mAssistant->activateStatusChanged(QString(""));
} else {
if (status == linphone::AccountCreatorStatusRequestFailed)
if (status == linphone::AccountCreator::Status::RequestFailed)
emit mAssistant->activateStatusChanged(tr("requestFailed"));
else
emit mAssistant->activateStatusChanged(tr("emailActivationFailed"));
@ -122,15 +122,15 @@ private:
void onRecoverAccount (
const shared_ptr<linphone::AccountCreator> &,
linphone::AccountCreatorStatus status,
linphone::AccountCreator::Status status,
const string &
) override {
if (status == linphone::AccountCreatorStatusRequestOk) {
if (status == linphone::AccountCreator::Status::RequestOk) {
emit mAssistant->recoverStatusChanged(QString(""));
} else {
if (status == linphone::AccountCreatorStatusRequestFailed)
if (status == linphone::AccountCreator::Status::RequestFailed)
emit mAssistant->recoverStatusChanged(tr("requestFailed"));
else if (status == linphone::AccountCreatorStatusServerError)
else if (status == linphone::AccountCreator::Status::ServerError)
emit mAssistant->recoverStatusChanged(tr("cannotSendSms"));
else
emit mAssistant->recoverStatusChanged(tr("loginWithPhoneNumberFailed"));
@ -268,12 +268,12 @@ void AssistantModel::setEmail (const QString &email) {
QString error;
switch (mAccountCreator->setEmail(Utils::appStringToCoreString(email))) {
case linphone::AccountCreatorEmailStatusOk:
case linphone::AccountCreator::EmailStatus::Ok:
break;
case linphone::AccountCreatorEmailStatusMalformed:
case linphone::AccountCreator::EmailStatus::Malformed:
error = tr("emailStatusMalformed");
break;
case linphone::AccountCreatorEmailStatusInvalidCharacters:
case linphone::AccountCreator::EmailStatus::InvalidCharacters:
error = tr("emailStatusMalformedInvalidCharacters");
break;
}
@ -292,19 +292,19 @@ void AssistantModel::setPassword (const QString &password) {
QString error;
switch (mAccountCreator->setPassword(Utils::appStringToCoreString(password))) {
case linphone::AccountCreatorPasswordStatusOk:
case linphone::AccountCreator::PasswordStatus::Ok:
break;
case linphone::AccountCreatorPasswordStatusTooShort:
case linphone::AccountCreator::PasswordStatus::TooShort:
error = tr("passwordStatusTooShort").arg(config->getInt("assistant", "password_min_length", 1));
break;
case linphone::AccountCreatorPasswordStatusTooLong:
case linphone::AccountCreator::PasswordStatus::TooLong:
error = tr("passwordStatusTooLong").arg(config->getInt("assistant", "password_max_length", -1));
break;
case linphone::AccountCreatorPasswordStatusInvalidCharacters:
case linphone::AccountCreator::PasswordStatus::InvalidCharacters:
error = tr("passwordStatusInvalidCharacters")
.arg(Utils::coreStringToAppString(config->getString("assistant", "password_regex", "")));
break;
case linphone::AccountCreatorPasswordStatusMissingCharacters:
case linphone::AccountCreator::PasswordStatus::MissingCharacters:
error = tr("passwordStatusMissingCharacters")
.arg(Utils::coreStringToAppString(config->getString("assistant", "missing_characters", "")));
break;
@ -334,19 +334,21 @@ void AssistantModel::setPhoneNumber (const QString &phoneNumber) {
shared_ptr<linphone::Config> config = CoreManager::getInstance()->getCore()->getConfig();
QString error;
switch (mAccountCreator->setPhoneNumber(Utils::appStringToCoreString(phoneNumber), Utils::appStringToCoreString(mCountryCode))) {
case linphone::AccountCreatorPhoneNumberStatusOk:
switch (static_cast<linphone::AccountCreator::PhoneNumberStatus>(
mAccountCreator->setPhoneNumber(Utils::appStringToCoreString(phoneNumber), Utils::appStringToCoreString(mCountryCode))
)) {
case linphone::AccountCreator::PhoneNumberStatus::Ok:
break;
case linphone::AccountCreatorPhoneNumberStatusInvalid:
case linphone::AccountCreator::PhoneNumberStatus::Invalid:
error = tr("phoneNumberStatusInvalid");
break;
case linphone::AccountCreatorPhoneNumberStatusTooShort:
case linphone::AccountCreator::PhoneNumberStatus::TooShort:
error = tr("phoneNumberStatusTooShort");
break;
case linphone::AccountCreatorPhoneNumberStatusTooLong:
case linphone::AccountCreator::PhoneNumberStatus::TooLong:
error = tr("phoneNumberStatusTooLong");
break;
case linphone::AccountCreatorPhoneNumberStatusInvalidCountryCode:
case linphone::AccountCreator::PhoneNumberStatus::InvalidCountryCode:
error = tr("phoneNumberStatusInvalidCountryCode");
break;
default:
@ -418,24 +420,24 @@ void AssistantModel::setConfigFilename (const QString &configFilename) {
// -----------------------------------------------------------------------------
QString AssistantModel::mapAccountCreatorUsernameStatusToString (linphone::AccountCreatorUsernameStatus status) const {
QString AssistantModel::mapAccountCreatorUsernameStatusToString (linphone::AccountCreator::UsernameStatus status) const {
shared_ptr<linphone::Config> config = CoreManager::getInstance()->getCore()->getConfig();
QString error;
switch (status) {
case linphone::AccountCreatorUsernameStatusOk:
case linphone::AccountCreator::UsernameStatus::Ok:
break;
case linphone::AccountCreatorUsernameStatusTooShort:
case linphone::AccountCreator::UsernameStatus::TooShort:
error = tr("usernameStatusTooShort").arg(config->getInt("assistant", "username_min_length", 1));
break;
case linphone::AccountCreatorUsernameStatusTooLong:
case linphone::AccountCreator::UsernameStatus::TooLong:
error = tr("usernameStatusTooLong").arg(config->getInt("assistant", "username_max_length", -1));
break;
case linphone::AccountCreatorUsernameStatusInvalidCharacters:
case linphone::AccountCreator::UsernameStatus::InvalidCharacters:
error = tr("usernameStatusInvalidCharacters")
.arg(Utils::coreStringToAppString(config->getString("assistant", "username_regex", "")));
break;
case linphone::AccountCreatorUsernameStatusInvalid:
case linphone::AccountCreator::UsernameStatus::Invalid:
error = tr("usernameStatusInvalid");
break;
}

View file

@ -94,7 +94,7 @@ private:
QString getConfigFilename () const;
void setConfigFilename (const QString &configFilename);
QString mapAccountCreatorUsernameStatusToString (linphone::AccountCreatorUsernameStatus status) const;
QString mapAccountCreatorUsernameStatusToString (linphone::AccountCreator::UsernameStatus status) const;
QString mCountryCode;
QString mConfigFilename;

View file

@ -87,10 +87,14 @@ CallModel::~CallModel () {
// -----------------------------------------------------------------------------
QString CallModel::getSipAddress () const {
QString CallModel::getPeerAddress () const {
return Utils::coreStringToAppString(mCall->getRemoteAddress()->asString());
}
QString CallModel::getLocalAddress () const {
return Utils::coreStringToAppString(mCall->getCallLog()->getFromAddress()->asString());
}
// -----------------------------------------------------------------------------
void CallModel::setRecordFile (const shared_ptr<linphone::CallParams> &callParams) {
@ -119,14 +123,14 @@ void CallModel::setRecordFile (const shared_ptr<linphone::CallParams> &callParam
void CallModel::updateStats (const shared_ptr<const linphone::CallStats> &callStats) {
switch (callStats->getType()) {
case linphone::StreamTypeText:
case linphone::StreamTypeUnknown:
case linphone::StreamType::Text:
case linphone::StreamType::Unknown:
break;
case linphone::StreamTypeAudio:
case linphone::StreamType::Audio:
updateStats(callStats, mAudioStats);
break;
case linphone::StreamTypeVideo:
case linphone::StreamType::Video:
updateStats(callStats, mVideoStats);
break;
}
@ -262,64 +266,64 @@ void CallModel::handleCallEncryptionChanged (const shared_ptr<linphone::Call> &c
emit securityUpdated();
}
void CallModel::handleCallStateChanged (const shared_ptr<linphone::Call> &call, linphone::CallState state) {
void CallModel::handleCallStateChanged (const shared_ptr<linphone::Call> &call, linphone::Call::State state) {
if (call != mCall)
return;
updateIsInConference();
switch (state) {
case linphone::CallStateError:
case linphone::CallStateEnd:
case linphone::Call::State::Error:
case linphone::Call::State::End:
setCallErrorFromReason(call->getReason());
stopAutoAnswerTimer();
stopRecording();
mPausedByRemote = false;
break;
case linphone::CallStateStreamsRunning:
case linphone::Call::State::StreamsRunning:
if (!mWasConnected && CoreManager::getInstance()->getSettingsModel()->getAutomaticallyRecordCalls()) {
startRecording();
mWasConnected = true;
} UTILS_NO_BREAK;
case linphone::CallStateConnected:
case linphone::CallStateRefered:
case linphone::CallStateReleased:
case linphone::Call::State::Connected:
case linphone::Call::State::Referred:
case linphone::Call::State::Released:
mPausedByRemote = false;
break;
case linphone::CallStatePausedByRemote:
case linphone::Call::State::PausedByRemote:
mNotifyCameraFirstFrameReceived = true;
mPausedByRemote = true;
break;
case linphone::CallStatePausing:
case linphone::Call::State::Pausing:
mNotifyCameraFirstFrameReceived = true;
mPausedByUser = true;
break;
case linphone::CallStateResuming:
case linphone::Call::State::Resuming:
mPausedByUser = false;
break;
case linphone::CallStateUpdatedByRemote:
case linphone::Call::State::UpdatedByRemote:
if (!mCall->getCurrentParams()->videoEnabled() && mCall->getRemoteParams()->videoEnabled()) {
mCall->deferUpdate();
emit videoRequested();
}
break;
case linphone::CallStateIdle:
case linphone::CallStateIncomingReceived:
case linphone::CallStateOutgoingInit:
case linphone::CallStateOutgoingProgress:
case linphone::CallStateOutgoingRinging:
case linphone::CallStateOutgoingEarlyMedia:
case linphone::CallStatePaused:
case linphone::CallStateIncomingEarlyMedia:
case linphone::CallStateUpdating:
case linphone::CallStateEarlyUpdatedByRemote:
case linphone::CallStateEarlyUpdating:
case linphone::Call::State::Idle:
case linphone::Call::State::IncomingReceived:
case linphone::Call::State::OutgoingInit:
case linphone::Call::State::OutgoingProgress:
case linphone::Call::State::OutgoingRinging:
case linphone::Call::State::OutgoingEarlyMedia:
case linphone::Call::State::Paused:
case linphone::Call::State::IncomingEarlyMedia:
case linphone::Call::State::Updating:
case linphone::Call::State::EarlyUpdatedByRemote:
case linphone::Call::State::EarlyUpdating:
break;
}
@ -372,39 +376,39 @@ void CallModel::stopAutoAnswerTimer () const {
CallModel::CallStatus CallModel::getStatus () const {
switch (mCall->getState()) {
case linphone::CallStateConnected:
case linphone::CallStateStreamsRunning:
case linphone::Call::State::Connected:
case linphone::Call::State::StreamsRunning:
return CallStatusConnected;
case linphone::CallStateEnd:
case linphone::CallStateError:
case linphone::CallStateRefered:
case linphone::CallStateReleased:
case linphone::Call::State::End:
case linphone::Call::State::Error:
case linphone::Call::State::Referred:
case linphone::Call::State::Released:
return CallStatusEnded;
case linphone::CallStatePaused:
case linphone::CallStatePausedByRemote:
case linphone::CallStatePausing:
case linphone::CallStateResuming:
case linphone::Call::State::Paused:
case linphone::Call::State::PausedByRemote:
case linphone::Call::State::Pausing:
case linphone::Call::State::Resuming:
return CallStatusPaused;
case linphone::CallStateUpdating:
case linphone::CallStateUpdatedByRemote:
case linphone::Call::State::Updating:
case linphone::Call::State::UpdatedByRemote:
return mPausedByRemote ? CallStatusPaused : CallStatusConnected;
case linphone::CallStateEarlyUpdatedByRemote:
case linphone::CallStateEarlyUpdating:
case linphone::CallStateIdle:
case linphone::CallStateIncomingEarlyMedia:
case linphone::CallStateIncomingReceived:
case linphone::CallStateOutgoingEarlyMedia:
case linphone::CallStateOutgoingInit:
case linphone::CallStateOutgoingProgress:
case linphone::CallStateOutgoingRinging:
case linphone::Call::State::EarlyUpdatedByRemote:
case linphone::Call::State::EarlyUpdating:
case linphone::Call::State::Idle:
case linphone::Call::State::IncomingEarlyMedia:
case linphone::Call::State::IncomingReceived:
case linphone::Call::State::OutgoingEarlyMedia:
case linphone::Call::State::OutgoingInit:
case linphone::Call::State::OutgoingProgress:
case linphone::Call::State::OutgoingRinging:
break;
}
return mCall->getDir() == linphone::CallDirIncoming ? CallStatusIncoming : CallStatusOutgoing;
return mCall->getDir() == linphone::Call::Dir::Incoming ? CallStatusIncoming : CallStatusOutgoing;
}
// -----------------------------------------------------------------------------
@ -430,16 +434,16 @@ QString CallModel::getCallError () const {
void CallModel::setCallErrorFromReason (linphone::Reason reason) {
switch (reason) {
case linphone::ReasonDeclined:
case linphone::Reason::Declined:
mCallError = tr("callErrorDeclined");
break;
case linphone::ReasonNotFound:
case linphone::Reason::NotFound:
mCallError = tr("callErrorNotFound");
break;
case linphone::ReasonBusy:
case linphone::Reason::Busy:
mCallError = tr("callErrorBusy");
break;
case linphone::ReasonNotAcceptable:
case linphone::Reason::NotAcceptable:
mCallError = tr("callErrorNotAcceptable");
break;
default:
@ -507,10 +511,10 @@ bool CallModel::getPausedByUser () const {
void CallModel::setPausedByUser (bool status) {
switch (mCall->getState()) {
case linphone::CallStateConnected:
case linphone::CallStateStreamsRunning:
case linphone::CallStatePaused:
case linphone::CallStatePausedByRemote:
case linphone::Call::State::Connected:
case linphone::Call::State::StreamsRunning:
case linphone::Call::State::Paused:
case linphone::Call::State::PausedByRemote:
break;
default: return;
}
@ -540,8 +544,8 @@ void CallModel::setVideoEnabled (bool status) {
}
switch (mCall->getState()) {
case linphone::CallStateConnected:
case linphone::CallStateStreamsRunning:
case linphone::Call::State::Connected:
case linphone::Call::State::StreamsRunning:
break;
default: return;
}
@ -559,10 +563,10 @@ void CallModel::setVideoEnabled (bool status) {
bool CallModel::getUpdating () const {
switch (mCall->getState()) {
case linphone::CallStateConnected:
case linphone::CallStateStreamsRunning:
case linphone::CallStatePaused:
case linphone::CallStatePausedByRemote:
case linphone::Call::State::Connected:
case linphone::Call::State::StreamsRunning:
case linphone::Call::State::Paused:
case linphone::Call::State::PausedByRemote:
return false;
default:
@ -602,33 +606,33 @@ bool CallModel::isSecured () const {
shared_ptr<const linphone::CallParams> params = mCall->getCurrentParams();
linphone::MediaEncryption encryption = params->getMediaEncryption();
return (
encryption == linphone::MediaEncryptionZRTP && mCall->getAuthenticationTokenVerified()
) || encryption == linphone::MediaEncryptionSRTP || encryption == linphone::MediaEncryptionDTLS;
encryption == linphone::MediaEncryption::ZRTP && mCall->getAuthenticationTokenVerified()
) || encryption == linphone::MediaEncryption::SRTP || encryption == linphone::MediaEncryption::DTLS;
}
// -----------------------------------------------------------------------------
QString CallModel::getLocalSas () const {
QString token = Utils::coreStringToAppString(mCall->getAuthenticationToken());
return mCall->getDir() == linphone::CallDirIncoming ? token.left(2).toUpper() : token.right(2).toUpper();
return mCall->getDir() == linphone::Call::Dir::Incoming ? token.left(2).toUpper() : token.right(2).toUpper();
}
QString CallModel::getRemoteSas () const {
QString token = Utils::coreStringToAppString(mCall->getAuthenticationToken());
return mCall->getDir() != linphone::CallDirIncoming ? token.left(2).toUpper() : token.right(2).toUpper();
return mCall->getDir() != linphone::Call::Dir::Incoming ? token.left(2).toUpper() : token.right(2).toUpper();
}
// -----------------------------------------------------------------------------
QString CallModel::getSecuredString () const {
switch (mCall->getCurrentParams()->getMediaEncryption()) {
case linphone::MediaEncryptionSRTP:
case linphone::MediaEncryption::SRTP:
return QStringLiteral("SRTP");
case linphone::MediaEncryptionZRTP:
case linphone::MediaEncryption::ZRTP:
return QStringLiteral("ZRTP");
case linphone::MediaEncryptionDTLS:
case linphone::MediaEncryption::DTLS:
return QStringLiteral("DTLS");
case linphone::MediaEncryptionNone:
case linphone::MediaEncryption::None:
break;
}
@ -659,10 +663,10 @@ void CallModel::updateStats (const shared_ptr<const linphone::CallStats> &callSt
shared_ptr<const linphone::PayloadType> payloadType;
switch (callStats->getType()) {
case linphone::StreamTypeAudio:
case linphone::StreamType::Audio:
payloadType = params->getUsedAudioPayloadType();
break;
case linphone::StreamTypeVideo:
case linphone::StreamType::Video:
payloadType = params->getUsedVideoPayloadType();
break;
default:
@ -671,10 +675,10 @@ void CallModel::updateStats (const shared_ptr<const linphone::CallStats> &callSt
QString family;
switch (callStats->getIpFamilyOfRemote()) {
case linphone::AddressFamilyInet:
case linphone::AddressFamily::Inet:
family = QStringLiteral("IPv4");
break;
case linphone::AddressFamilyInet6:
case linphone::AddressFamily::Inet6:
family = QStringLiteral("IPv6");
break;
default:
@ -695,10 +699,10 @@ void CallModel::updateStats (const shared_ptr<const linphone::CallStats> &callSt
statsList << createStat(tr("callStatsReceiverLossRate"), QStringLiteral("%1 %").arg(callStats->getReceiverLossRate()));
switch (callStats->getType()) {
case linphone::StreamTypeAudio:
case linphone::StreamType::Audio:
statsList << createStat(tr("callStatsJitterBuffer"), QStringLiteral("%1 ms").arg(callStats->getJitterBufferSizeMs()));
break;
case linphone::StreamTypeVideo: {
case linphone::StreamType::Video: {
statsList << createStat(tr("callStatsEstimatedDownloadBandwidth"), QStringLiteral("%1 kbits/s").arg(int(callStats->getEstimatedDownloadBandwidth())));
const QString sentVideoDefinitionName = Utils::coreStringToAppString(params->getSentVideoDefinition()->getName());
const QString sentVideoDefinition = QStringLiteral("%1x%2")
@ -731,17 +735,17 @@ void CallModel::updateStats (const shared_ptr<const linphone::CallStats> &callSt
QString CallModel::iceStateToString (linphone::IceState state) const {
switch (state) {
case linphone::IceStateNotActivated:
case linphone::IceState::NotActivated:
return tr("iceStateNotActivated");
case linphone::IceStateFailed:
case linphone::IceState::Failed:
return tr("iceStateFailed");
case linphone::IceStateInProgress:
case linphone::IceState::InProgress:
return tr("iceStateInProgress");
case linphone::IceStateReflexiveConnection:
case linphone::IceState::ReflexiveConnection:
return tr("iceStateReflexiveConnection");
case linphone::IceStateHostConnection:
case linphone::IceState::HostConnection:
return tr("iceStateHostConnection");
case linphone::IceStateRelayConnection:
case linphone::IceState::RelayConnection:
return tr("iceStateRelayConnection");
}

View file

@ -31,7 +31,9 @@
class CallModel : public QObject {
Q_OBJECT;
Q_PROPERTY(QString sipAddress READ getSipAddress CONSTANT);
Q_PROPERTY(QString peerAddress READ getPeerAddress CONSTANT);
Q_PROPERTY(QString localAddress READ getLocalAddress CONSTANT);
Q_PROPERTY(CallStatus status READ getStatus NOTIFY statusChanged);
Q_PROPERTY(QString callError READ getCallError NOTIFY callErrorChanged);
@ -77,10 +79,10 @@ public:
Q_ENUM(CallStatus);
enum CallEncryption {
CallEncryptionNone = linphone::MediaEncryptionNone,
CallEncryptionDtls = linphone::MediaEncryptionDTLS,
CallEncryptionSrtp = linphone::MediaEncryptionSRTP,
CallEncryptionZrtp = linphone::MediaEncryptionZRTP
CallEncryptionNone = int(linphone::MediaEncryption::None),
CallEncryptionDtls = int(linphone::MediaEncryption::DTLS),
CallEncryptionSrtp = int(linphone::MediaEncryption::SRTP),
CallEncryptionZrtp = int(linphone::MediaEncryption::ZRTP)
};
Q_ENUM(CallEncryption);
@ -91,7 +93,8 @@ public:
return mCall;
}
QString getSipAddress () const;
QString getPeerAddress () const;
QString getLocalAddress () const;
bool isInConference () const {
return mIsInConference;
@ -140,7 +143,7 @@ signals:
private:
void handleCallEncryptionChanged (const std::shared_ptr<linphone::Call> &call);
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::CallState state);
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
void accept (bool withVideo);
@ -149,7 +152,7 @@ private:
CallStatus getStatus () const;
bool isOutgoing () const {
return mCall->getDir() == linphone::CallDirOutgoing;
return mCall->getDir() == linphone::Call::Dir::Outgoing;
}
void updateIsInConference ();

View file

@ -179,23 +179,23 @@ static void joinConference (const shared_ptr<linphone::Call> &call) {
addModel->update();
}
void CallsListModel::handleCallStateChanged (const shared_ptr<linphone::Call> &call, linphone::CallState state) {
void CallsListModel::handleCallStateChanged (const shared_ptr<linphone::Call> &call, linphone::Call::State state) {
switch (state) {
case linphone::CallStateIncomingReceived:
case linphone::Call::State::IncomingReceived:
addCall(call);
joinConference(call);
break;
case linphone::CallStateOutgoingInit:
case linphone::Call::State::OutgoingInit:
addCall(call);
break;
case linphone::CallStateEnd:
case linphone::CallStateError:
case linphone::Call::State::End:
case linphone::Call::State::Error:
removeCall(call);
break;
case linphone::CallStateStreamsRunning: {
case linphone::Call::State::StreamsRunning: {
int index = findCallIndex(mList, call);
emit callRunning(index, &call->getData<CallModel>("call-model"));
} break;
@ -228,7 +228,7 @@ bool CallsListModel::removeRows (int row, int count, const QModelIndex &parent)
// -----------------------------------------------------------------------------
void CallsListModel::addCall (const shared_ptr<linphone::Call> &call) {
if (call->getDir() == linphone::CallDirOutgoing) {
if (call->getDir() == linphone::Call::Dir::Outgoing) {
QQuickWindow *callsWindow = App::getInstance()->getCallsWindow();
if (callsWindow) {
if (CoreManager::getInstance()->getSettingsModel()->getKeepCallsWindowInBackground()) {

View file

@ -59,7 +59,7 @@ private:
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::CallState state);
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
void addCall (const std::shared_ptr<linphone::Call> &call);
void removeCall (const std::shared_ptr<linphone::Call> &call);

View file

@ -24,6 +24,7 @@
#include <QDateTime>
#include <QDesktopServices>
#include <QElapsedTimer>
#include <QFileInfo>
#include <QMimeDatabase>
#include <QTimer>
@ -132,6 +133,46 @@ static inline void removeFileMessageThumbnail (const shared_ptr<linphone::ChatMe
// -----------------------------------------------------------------------------
static inline void fillMessageEntry (QVariantMap &dest, const shared_ptr<linphone::ChatMessage> &message) {
dest["content"] = Utils::coreStringToAppString(message->getText());
dest["isOutgoing"] = message->isOutgoing() || message->getState() == linphone::ChatMessage::State::Idle;
// Old workaround.
// It can exist messages with a not delivered status. It's a linphone core bug.
linphone::ChatMessage::State state = message->getState();
if (state == linphone::ChatMessage::State::InProgress)
dest["status"] = ChatModel::MessageStatusNotDelivered;
else
dest["status"] = static_cast<ChatModel::MessageStatus>(message->getState());
shared_ptr<const linphone::Content> content = message->getFileTransferInformation();
if (content) {
dest["fileSize"] = quint64(content->getSize());
dest["fileName"] = Utils::coreStringToAppString(content->getName());
dest["wasDownloaded"] = ::fileWasDownloaded(message);
fillThumbnailProperty(dest, message);
}
}
static inline void fillCallStartEntry (QVariantMap &dest, const shared_ptr<linphone::CallLog> &callLog) {
dest["type"] = ChatModel::CallEntry;
dest["timestamp"] = QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000);
dest["isOutgoing"] = callLog->getDir() == linphone::Call::Dir::Outgoing;
dest["status"] = static_cast<ChatModel::CallStatus>(callLog->getStatus());
dest["isStart"] = true;
}
static inline void fillCallEndEntry (QVariantMap &dest, const shared_ptr<linphone::CallLog> &callLog) {
dest["type"] = ChatModel::CallEntry;
dest["timestamp"] = QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000);
dest["isOutgoing"] = callLog->getDir() == linphone::Call::Dir::Outgoing;
dest["status"] = static_cast<ChatModel::CallStatus>(callLog->getStatus());
dest["isStart"] = false;
}
// -----------------------------------------------------------------------------
class ChatModel::MessageHandlers : public linphone::ChatMessageListener {
friend class ChatModel;
@ -178,7 +219,7 @@ private:
signalDataChanged(it);
}
void onMsgStateChanged (const shared_ptr<linphone::ChatMessage> &message, linphone::ChatMessageState state) override {
void onMsgStateChanged (const shared_ptr<linphone::ChatMessage> &message, linphone::ChatMessage::State state) override {
if (!mChatModel)
return;
@ -187,7 +228,7 @@ private:
return;
// File message downloaded.
if (state == linphone::ChatMessageStateFileTransferDone && !message->isOutgoing()) {
if (state == linphone::ChatMessage::State::FileTransferDone && !message->isOutgoing()) {
createThumbnail(message);
fillThumbnailProperty((*it).first, message);
@ -199,7 +240,7 @@ private:
App::getInstance()->getNotifier()->notifyReceivedFileMessage(message);
}
(*it).first["status"] = state;
(*it).first["status"] = static_cast<MessageStatus>(state);
signalDataChanged(it);
}
@ -209,13 +250,13 @@ private:
// -----------------------------------------------------------------------------
ChatModel::ChatModel (const QString &sipAddress) {
ChatModel::ChatModel (const QString &peerAddress, const QString &localAddress) {
CoreManager *coreManager = CoreManager::getInstance();
mCoreHandlers = coreManager->getHandlers();
mMessageHandlers = make_shared<MessageHandlers>(this);
setSipAddress(sipAddress);
setSipAddresses(peerAddress, localAddress);
{
CoreHandlers *coreHandlers = mCoreHandlers.get();
@ -247,8 +288,12 @@ QVariant ChatModel::data (const QModelIndex &index, int role) const {
return QVariant();
switch (role) {
case Roles::ChatEntry:
return QVariant::fromValue(mEntries[row].first);
case Roles::ChatEntry: {
auto &data = mEntries[row].first;
if (!data.contains("status"))
fillMessageEntry(data, static_pointer_cast<linphone::ChatMessage>(mEntries[row].second));
return QVariant::fromValue(data);
}
case Roles::SectionDate:
return QVariant::fromValue(mEntries[row].first["timestamp"].toDate());
}
@ -283,38 +328,53 @@ bool ChatModel::removeRows (int row, int count, const QModelIndex &parent) {
return true;
}
QString ChatModel::getSipAddress () const {
QString ChatModel::getPeerAddress () const {
return Utils::coreStringToAppString(
mChatRoom->getPeerAddress()->asStringUriOnly()
);
}
void ChatModel::setSipAddress (const QString &sipAddress) {
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
QString ChatModel::getLocalAddress () const {
return Utils::coreStringToAppString(
mChatRoom->getLocalAddress()->asStringUriOnly()
);
}
mChatRoom = core->getChatRoomFromUri(Utils::appStringToCoreString(sipAddress));
Q_CHECK_PTR(mChatRoom.get());
void ChatModel::setSipAddresses (const QString &peerAddress, const QString &localAddress) {
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
shared_ptr<linphone::Factory> factory(linphone::Factory::get());
mChatRoom = core->getChatRoom(
factory->createAddress(Utils::appStringToCoreString(peerAddress)),
factory->createAddress(Utils::appStringToCoreString(localAddress))
);
Q_ASSERT(mChatRoom);
handleIsComposingChanged(mChatRoom);
// Get messages.
mEntries.clear();
for (auto &message : mChatRoom->getHistory(0)) {
QVariantMap map;
fillMessageEntry(map, message);
QElapsedTimer timer;
timer.start();
// Old workaround.
// It can exist messages with a not delivered status. It's a linphone core bug.
if (message->getState() == linphone::ChatMessageStateInProgress)
map["status"] = linphone::ChatMessageStateNotDelivered;
mEntries << qMakePair(map, static_pointer_cast<void>(message));
}
for (auto &message : mChatRoom->getHistory(0))
mEntries << qMakePair(
QVariantMap{
{ "type", EntryType::MessageEntry },
{ "timestamp", QDateTime::fromMSecsSinceEpoch(message->getTime() * 1000) }
},
static_pointer_cast<void>(message)
);
// Get calls.
// TODO: Add an API to find with local and peer addresses.
for (auto &callLog : core->getCallHistoryForAddress(mChatRoom->getPeerAddress()))
insertCall(callLog);
if (mChatRoom->getLocalAddress()->weakEqual(callLog->getLocalAddress()))
insertCall(callLog);
qInfo() << QStringLiteral("ChatModel (%1, %2) loaded in %3 milliseconds.")
.arg(peerAddress).arg(localAddress).arg(timer.elapsed());
}
bool ChatModel::getIsRemoteComposing () const {
@ -324,15 +384,16 @@ bool ChatModel::getIsRemoteComposing () const {
// -----------------------------------------------------------------------------
void ChatModel::removeEntry (int id) {
qInfo() << QStringLiteral("Removing chat entry: %1 of %2.")
.arg(id).arg(getSipAddress());
qInfo() << QStringLiteral("Removing chat entry: %1 of (%2, %3).")
.arg(id).arg(getPeerAddress()).arg(getLocalAddress());
if (!removeRow(id))
qWarning() << QStringLiteral("Unable to remove chat entry: %1").arg(id);
}
void ChatModel::removeAllEntries () {
qInfo() << QStringLiteral("Removing all chat entries of: %1.").arg(getSipAddress());
qInfo() << QStringLiteral("Removing all chat entries of: (%1, %2).")
.arg(getPeerAddress()).arg(getLocalAddress());
beginResetModel();
@ -433,7 +494,7 @@ void ChatModel::downloadFile (int id) {
shared_ptr<linphone::ChatMessage> message = static_pointer_cast<linphone::ChatMessage>(entry.second);
switch (message->getState()) {
switch (static_cast<MessageStatus>(message->getState())) {
case MessageStatusDelivered:
case MessageStatusDeliveredToUser:
case MessageStatusDisplayed:
@ -461,7 +522,7 @@ void ChatModel::downloadFile (int id) {
message->setFileTransferFilepath(Utils::appStringToCoreString(safeFilePath));
message->setListener(mMessageHandlers);
if (message->downloadFile() < 0)
if (!message->downloadFile())
qWarning() << QStringLiteral("Unable to download file of entry %1.").arg(id);
}
@ -491,10 +552,10 @@ void ChatModel::compose () {
mChatRoom->compose();
}
void ChatModel::resetMessagesCount () {
void ChatModel::resetMessageCount () {
if (mChatRoom->getUnreadMessagesCount() > 0) {
mChatRoom->markAsRead();
emit messagesCountReset();
emit messageCountReset();
}
}
@ -523,45 +584,6 @@ const ChatModel::ChatEntryData ChatModel::getFileMessageEntry (int id) {
// -----------------------------------------------------------------------------
void ChatModel::fillMessageEntry (QVariantMap &dest, const shared_ptr<linphone::ChatMessage> &message) {
dest["type"] = EntryType::MessageEntry;
dest["timestamp"] = QDateTime::fromMSecsSinceEpoch(message->getTime() * 1000);
dest["content"] = Utils::coreStringToAppString(message->getText());
dest["isOutgoing"] = message->isOutgoing() || message->getState() == linphone::ChatMessageStateIdle;
dest["status"] = message->getState();
shared_ptr<const linphone::Content> content = message->getFileTransferInformation();
if (content) {
dest["fileSize"] = quint64(content->getSize());
dest["fileName"] = Utils::coreStringToAppString(content->getName());
dest["wasDownloaded"] = ::fileWasDownloaded(message);
fillThumbnailProperty(dest, message);
}
}
void ChatModel::fillCallStartEntry (QVariantMap &dest, const shared_ptr<linphone::CallLog> &callLog) {
QDateTime timestamp = QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000);
dest["type"] = EntryType::CallEntry;
dest["timestamp"] = timestamp;
dest["isOutgoing"] = callLog->getDir() == linphone::CallDirOutgoing;
dest["status"] = callLog->getStatus();
dest["isStart"] = true;
}
void ChatModel::fillCallEndEntry (QVariantMap &dest, const shared_ptr<linphone::CallLog> &callLog) {
QDateTime timestamp = QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000);
dest["type"] = EntryType::CallEntry;
dest["timestamp"] = timestamp;
dest["isOutgoing"] = callLog->getDir() == linphone::CallDirOutgoing;
dest["status"] = callLog->getStatus();
dest["isStart"] = false;
}
// -----------------------------------------------------------------------------
void ChatModel::removeEntry (ChatEntryData &entry) {
int type = entry.first["type"].toInt();
@ -574,7 +596,7 @@ void ChatModel::removeEntry (ChatEntryData &entry) {
}
case ChatModel::CallEntry: {
if (entry.first["status"].toInt() == linphone::CallStatusSuccess) {
if (entry.first["status"].toInt() == CallStatusSuccess) {
// WARNING: Unable to remove symmetric call here. (start/end)
// We are between `beginRemoveRows` and `endRemoveRows`.
// A solution is to schedule a `removeEntry` call in the Qt main loop.
@ -599,20 +621,19 @@ void ChatModel::removeEntry (ChatEntryData &entry) {
}
void ChatModel::insertCall (const shared_ptr<linphone::CallLog> &callLog) {
linphone::CallStatus status = callLog->getStatus();
linphone::Call::Status status = callLog->getStatus();
switch (status) {
case linphone::CallStatusAborted:
case linphone::CallStatusEarlyAborted:
case linphone::Call::Status::Aborted:
case linphone::Call::Status::EarlyAborted:
return; // Ignore aborted calls.
case linphone::CallStatusAcceptedElsewhere:
case linphone::CallStatusDeclinedElsewhere:
case linphone::Call::Status::AcceptedElsewhere:
case linphone::Call::Status::DeclinedElsewhere:
return; // Ignore accepted calls on other device.
case linphone::CallStatusSuccess:
case linphone::CallStatusMissed:
case linphone::CallStatusDeclined:
case linphone::Call::Status::Success:
case linphone::Call::Status::Missed:
case linphone::Call::Status::Declined:
break;
}
@ -639,7 +660,7 @@ void ChatModel::insertCall (const shared_ptr<linphone::CallLog> &callLog) {
auto it = insertEntry(qMakePair(start, static_pointer_cast<void>(callLog)));
// Add end call. (if necessary)
if (status == linphone::CallStatusSuccess) {
if (status == linphone::Call::Status::Success) {
QVariantMap end;
fillCallEndEntry(end, callLog);
insertEntry(qMakePair(end, static_pointer_cast<void>(callLog)), &it);
@ -651,7 +672,10 @@ void ChatModel::insertMessageAtEnd (const shared_ptr<linphone::ChatMessage> &mes
beginInsertRows(QModelIndex(), row, row);
QVariantMap map;
QVariantMap map{
{ "type", EntryType::MessageEntry },
{ "timestamp", QDateTime::fromMSecsSinceEpoch(message->getTime() * 1000) }
};
fillMessageEntry(map, message);
mEntries << qMakePair(map, static_pointer_cast<void>(message));
@ -660,10 +684,10 @@ void ChatModel::insertMessageAtEnd (const shared_ptr<linphone::ChatMessage> &mes
// -----------------------------------------------------------------------------
void ChatModel::handleCallStateChanged (const shared_ptr<linphone::Call> &call, linphone::CallState state) {
void ChatModel::handleCallStateChanged (const shared_ptr<linphone::Call> &call, linphone::Call::State state) {
if (
(state == linphone::CallStateEnd || state == linphone::CallStateError) &&
mChatRoom == CoreManager::getInstance()->getCore()->getChatRoom(call->getRemoteAddress())
(state == linphone::Call::State::End || state == linphone::Call::State::Error) &&
mChatRoom == CoreManager::getInstance()->getCore()->findChatRoom(call->getRemoteAddress(), mChatRoom->getLocalAddress())
)
insertCall(call->getCallLog());
}

View file

@ -51,25 +51,25 @@ public:
Q_ENUM(EntryType);
enum CallStatus {
CallStatusDeclined = linphone::CallStatusDeclined,
CallStatusMissed = linphone::CallStatusMissed,
CallStatusSuccess = linphone::CallStatusSuccess
CallStatusDeclined = int(linphone::Call::Status::Declined),
CallStatusMissed = int(linphone::Call::Status::Missed),
CallStatusSuccess = int(linphone::Call::Status::Success)
};
Q_ENUM(CallStatus);
enum MessageStatus {
MessageStatusDelivered = linphone::ChatMessageStateDelivered,
MessageStatusDeliveredToUser = linphone::ChatMessageStateDeliveredToUser,
MessageStatusDisplayed = linphone::ChatMessageStateDisplayed,
MessageStatusFileTransferDone = linphone::ChatMessageStateFileTransferDone,
MessageStatusFileTransferError = linphone::ChatMessageStateFileTransferError,
MessageStatusIdle = linphone::ChatMessageStateIdle,
MessageStatusInProgress = linphone::ChatMessageStateInProgress,
MessageStatusNotDelivered = linphone::ChatMessageStateNotDelivered
MessageStatusDelivered = int(linphone::ChatMessage::State::Delivered),
MessageStatusDeliveredToUser = int(linphone::ChatMessage::State::DeliveredToUser),
MessageStatusDisplayed = int(linphone::ChatMessage::State::Displayed),
MessageStatusFileTransferDone = int(linphone::ChatMessage::State::FileTransferDone),
MessageStatusFileTransferError = int(linphone::ChatMessage::State::FileTransferError),
MessageStatusIdle = int(linphone::ChatMessage::State::Idle),
MessageStatusInProgress = int(linphone::ChatMessage::State::InProgress),
MessageStatusNotDelivered = int(linphone::ChatMessage::State::NotDelivered)
};
Q_ENUM(MessageStatus);
ChatModel (const QString &sipAddress);
ChatModel (const QString &peerAddress, const QString &localAddress);
~ChatModel ();
int rowCount (const QModelIndex &index = QModelIndex()) const override;
@ -80,7 +80,8 @@ public:
bool removeRow (int row, const QModelIndex &parent = QModelIndex());
bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;
QString getSipAddress () const;
QString getPeerAddress () const;
QString getLocalAddress () const;
bool getIsRemoteComposing () const;
@ -103,7 +104,7 @@ public:
void compose ();
void resetMessagesCount ();
void resetMessageCount ();
signals:
bool isRemoteComposingChanged (bool status);
@ -114,31 +115,27 @@ signals:
void messageSent (const std::shared_ptr<linphone::ChatMessage> &message);
void messageReceived (const std::shared_ptr<linphone::ChatMessage> &message);
void messagesCountReset ();
void messageCountReset ();
private:
typedef QPair<QVariantMap, std::shared_ptr<void>> ChatEntryData;
void setSipAddress (const QString &sipAddress);
void setSipAddresses (const QString &peerAddress, const QString &localAddress);
const ChatEntryData getFileMessageEntry (int id);
void fillMessageEntry (QVariantMap &dest, const std::shared_ptr<linphone::ChatMessage> &message);
void fillCallStartEntry (QVariantMap &dest, const std::shared_ptr<linphone::CallLog> &callLog);
void fillCallEndEntry (QVariantMap &dest, const std::shared_ptr<linphone::CallLog> &callLog);
void removeEntry (ChatEntryData &entry);
void insertCall (const std::shared_ptr<linphone::CallLog> &callLog);
void insertMessageAtEnd (const std::shared_ptr<linphone::ChatMessage> &message);
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::CallState state);
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
void handleIsComposingChanged (const std::shared_ptr<linphone::ChatRoom> &chatRoom);
void handleMessageReceived (const std::shared_ptr<linphone::ChatMessage> &message);
bool mIsRemoteComposing = false;
QList<ChatEntryData> mEntries;
mutable QList<ChatEntryData> mEntries;
std::shared_ptr<linphone::ChatRoom> mChatRoom;
std::shared_ptr<CoreHandlers> mCoreHandlers;

View file

@ -85,17 +85,17 @@ ChatProxyModel::ChatProxyModel (QObject *parent) : QSortFilterProxyModel(parent)
mChatModel
#define CREATE_PARENT_MODEL_FUNCTION(METHOD) \
void ChatProxyModel::METHOD() { \
void ChatProxyModel::METHOD () { \
GET_CHAT_MODEL()->METHOD(); \
}
#define CREATE_PARENT_MODEL_FUNCTION_WITH_PARAM(METHOD, ARG_TYPE) \
void ChatProxyModel::METHOD(ARG_TYPE value) { \
void ChatProxyModel::METHOD (ARG_TYPE value) { \
GET_CHAT_MODEL()->METHOD(value); \
}
#define CREATE_PARENT_MODEL_FUNCTION_WITH_ID(METHOD) \
void ChatProxyModel::METHOD(int id) { \
void ChatProxyModel::METHOD (int id) { \
QModelIndex sourceIndex = mapToSource(index(id, 0)); \
GET_CHAT_MODEL()->METHOD( \
static_cast<ChatModelFilter *>(sourceModel())->mapToSource(sourceIndex).row() \
@ -156,11 +156,31 @@ bool ChatProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &) const
// -----------------------------------------------------------------------------
QString ChatProxyModel::getSipAddress () const {
return mChatModel ? mChatModel->getSipAddress() : QString("");
QString ChatProxyModel::getPeerAddress () const {
return mChatModel ? mChatModel->getPeerAddress() : QString("");
}
void ChatProxyModel::setSipAddress (const QString &sipAddress) {
void ChatProxyModel::setPeerAddress (const QString &peerAddress) {
mPeerAddress = peerAddress;
reload();
}
QString ChatProxyModel::getLocalAddress () const {
return mChatModel ? mChatModel->getLocalAddress() : QString("");
}
void ChatProxyModel::setLocalAddress (const QString &localAddress) {
mLocalAddress = localAddress;
reload();
}
bool ChatProxyModel::getIsRemoteComposing () const {
return mChatModel ? mChatModel->getIsRemoteComposing() : false;
}
// -----------------------------------------------------------------------------
void ChatProxyModel::reload () {
mMaxDisplayedEntries = EntriesChunkSize;
if (mChatModel) {
@ -170,10 +190,10 @@ void ChatProxyModel::setSipAddress (const QString &sipAddress) {
QObject::disconnect(chatModel, &ChatModel::messageSent, this, &ChatProxyModel::handleMessageSent);
}
mChatModel = CoreManager::getInstance()->getChatModelFromSipAddress(sipAddress);
mChatModel = CoreManager::getInstance()->getChatModel(mPeerAddress, mLocalAddress);
if (mChatModel) {
mChatModel->resetMessagesCount();
mChatModel->resetMessageCount();
ChatModel *chatModel = mChatModel.get();
QObject::connect(chatModel, &ChatModel::isRemoteComposingChanged, this, &ChatProxyModel::handleIsRemoteComposingChanged);
@ -184,10 +204,6 @@ void ChatProxyModel::setSipAddress (const QString &sipAddress) {
static_cast<ChatModelFilter *>(sourceModel())->setSourceModel(mChatModel.get());
}
bool ChatProxyModel::getIsRemoteComposing () const {
return mChatModel ? mChatModel->getIsRemoteComposing() : false;
}
// -----------------------------------------------------------------------------
static inline QWindow *getParentWindow (QObject *object) {
@ -201,8 +217,8 @@ static inline QWindow *getParentWindow (QObject *object) {
}
void ChatProxyModel::handleIsActiveChanged (QWindow *window) {
if (window->isActive() && getParentWindow(this) == window)
mChatModel->resetMessagesCount();
if (mChatModel && window->isActive() && getParentWindow(this) == window)
mChatModel->resetMessageCount();
}
void ChatProxyModel::handleIsRemoteComposingChanged (bool status) {
@ -214,7 +230,7 @@ void ChatProxyModel::handleMessageReceived (const shared_ptr<linphone::ChatMessa
QWindow *window = getParentWindow(this);
if (window && window->isActive())
mChatModel->resetMessagesCount();
mChatModel->resetMessageCount();
}
void ChatProxyModel::handleMessageSent (const shared_ptr<linphone::ChatMessage> &) {

View file

@ -36,7 +36,8 @@ class ChatProxyModel : public QSortFilterProxyModel {
Q_OBJECT;
Q_PROPERTY(QString sipAddress READ getSipAddress WRITE setSipAddress NOTIFY sipAddressChanged);
Q_PROPERTY(QString peerAddress READ getPeerAddress WRITE setPeerAddress NOTIFY peerAddressChanged);
Q_PROPERTY(QString localAddress READ getLocalAddress WRITE setLocalAddress NOTIFY localAddressChanged);
Q_PROPERTY(bool isRemoteComposing READ getIsRemoteComposing NOTIFY isRemoteComposingChanged);
public:
@ -60,7 +61,8 @@ public:
Q_INVOKABLE void compose ();
signals:
void sipAddressChanged (const QString &sipAddress);
void peerAddressChanged (const QString &peerAddress);
void localAddressChanged (const QString &localAddress);
bool isRemoteComposingChanged (bool status);
void moreEntriesLoaded (int n);
@ -71,11 +73,16 @@ protected:
bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
private:
QString getSipAddress () const;
void setSipAddress (const QString &sipAddress);
QString getPeerAddress () const;
void setPeerAddress (const QString &peerAddress);
QString getLocalAddress () const;
void setLocalAddress (const QString &localAddress);
bool getIsRemoteComposing () const;
void reload ();
void handleIsActiveChanged (QWindow *window);
void handleIsRemoteComposingChanged (bool status);
@ -84,6 +91,9 @@ private:
int mMaxDisplayedEntries = EntriesChunkSize;
QString mPeerAddress;
QString mLocalAddress;
std::shared_ptr<ChatModel> mChatModel;
static constexpr int EntriesChunkSize = 50;

View file

@ -140,10 +140,7 @@ ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) {
contact = new ContactModel(this, vcardModel);
App::getInstance()->getEngine()->setObjectOwnership(contact, QQmlEngine::CppOwnership);
if (
mLinphoneFriends->addFriend(contact->mLinphoneFriend) !=
linphone::FriendListStatus::FriendListStatusOK
) {
if (mLinphoneFriends->addFriend(contact->mLinphoneFriend) != linphone::FriendList::Status::OK) {
qWarning() << QStringLiteral("Unable to add contact from vcard:") << vcardModel;
delete contact;
return nullptr;

View file

@ -29,6 +29,7 @@
#include "components/call/CallModel.hpp"
#include "components/contact/ContactModel.hpp"
#include "components/notifier/Notifier.hpp"
#include "components/settings/AccountSettingsModel.hpp"
#include "components/settings/SettingsModel.hpp"
#include "utils/Utils.hpp"
@ -101,14 +102,14 @@ void CoreHandlers::onCallEncryptionChanged (
void CoreHandlers::onCallStateChanged (
const shared_ptr<linphone::Core> &,
const shared_ptr<linphone::Call> &call,
linphone::CallState state,
linphone::Call::State state,
const string &
) {
emit callStateChanged(call, state);
SettingsModel *settingsModel = CoreManager::getInstance()->getSettingsModel();
if (
call->getState() == linphone::CallStateIncomingReceived && (
call->getState() == linphone::Call::State::IncomingReceived && (
!settingsModel->getAutoAnswerStatus() ||
settingsModel->getAutoAnswerDelay() > 0
)
@ -129,7 +130,7 @@ void CoreHandlers::onGlobalStateChanged (
linphone::GlobalState gstate,
const string &
) {
if (gstate == linphone::GlobalStateOn) {
if (gstate == linphone::GlobalState::On) {
mCoreStartedLock->lock();
Q_ASSERT(mCoreStarted == false);
@ -149,7 +150,7 @@ void CoreHandlers::onIsComposingReceived (
void CoreHandlers::onLogCollectionUploadStateChanged (
const shared_ptr<linphone::Core> &,
linphone::CoreLogCollectionUploadState state,
linphone::Core::LogCollectionUploadState state,
const string &info
) {
emit logsUploadStateChanged(state, info);
@ -165,7 +166,7 @@ void CoreHandlers::onLogCollectionUploadProgressIndication (
void CoreHandlers::onMessageReceived (
const shared_ptr<linphone::Core> &core,
const shared_ptr<linphone::ChatRoom> &,
const shared_ptr<linphone::ChatRoom> &chatRoom,
const shared_ptr<linphone::ChatMessage> &message
) {
const string contentType = message->getContentType();
@ -174,13 +175,14 @@ void CoreHandlers::onMessageReceived (
emit messageReceived(message);
// 1. Do not notify if chat is not activated.
SettingsModel *settingsModel = CoreManager::getInstance()->getSettingsModel();
CoreManager *coreManager = CoreManager::getInstance();
SettingsModel *settingsModel = coreManager->getSettingsModel();
if (!settingsModel->getChatEnabled())
return;
// 2. Notify with Notification popup.
const App *app = App::getInstance();
if (!app->hasFocus())
if (!app->hasFocus() || !chatRoom->getLocalAddress()->weakEqual(coreManager->getAccountSettingsModel()->getUsedSipAddress()))
app->getNotifier()->notifyReceivedMessage(message);
// 3. Notify with sound.
@ -190,7 +192,8 @@ void CoreHandlers::onMessageReceived (
if (
!app->hasFocus() ||
!CoreManager::getInstance()->chatModelExists(
Utils::coreStringToAppString(message->getFromAddress()->asStringUriOnly())
Utils::coreStringToAppString(chatRoom->getPeerAddress()->asStringUriOnly()),
Utils::coreStringToAppString(chatRoom->getLocalAddress()->asStringUriOnly())
)
)
core->playLocal(Utils::appStringToCoreString(settingsModel->getChatNotificationSoundPath()));
@ -227,46 +230,46 @@ void CoreHandlers::onRegistrationStateChanged (
void CoreHandlers::onTransferStateChanged (
const shared_ptr<linphone::Core> &,
const shared_ptr<linphone::Call> &call,
linphone::CallState state
linphone::Call::State state
) {
switch (state) {
case linphone::CallStateEarlyUpdatedByRemote:
case linphone::CallStateEarlyUpdating:
case linphone::CallStateIdle:
case linphone::CallStateIncomingEarlyMedia:
case linphone::CallStateIncomingReceived:
case linphone::CallStateOutgoingEarlyMedia:
case linphone::CallStateOutgoingRinging:
case linphone::CallStatePaused:
case linphone::CallStatePausedByRemote:
case linphone::CallStatePausing:
case linphone::CallStateRefered:
case linphone::CallStateReleased:
case linphone::CallStateResuming:
case linphone::CallStateStreamsRunning:
case linphone::CallStateUpdatedByRemote:
case linphone::CallStateUpdating:
case linphone::Call::State::EarlyUpdatedByRemote:
case linphone::Call::State::EarlyUpdating:
case linphone::Call::State::Idle:
case linphone::Call::State::IncomingEarlyMedia:
case linphone::Call::State::IncomingReceived:
case linphone::Call::State::OutgoingEarlyMedia:
case linphone::Call::State::OutgoingRinging:
case linphone::Call::State::Paused:
case linphone::Call::State::PausedByRemote:
case linphone::Call::State::Pausing:
case linphone::Call::State::Referred:
case linphone::Call::State::Released:
case linphone::Call::State::Resuming:
case linphone::Call::State::StreamsRunning:
case linphone::Call::State::UpdatedByRemote:
case linphone::Call::State::Updating:
break; // Nothing.
// 1. Init.
case linphone::CallStateOutgoingInit:
case linphone::Call::State::OutgoingInit:
qInfo() << QStringLiteral("Call transfer init.");
break;
// 2. In progress.
case linphone::CallStateOutgoingProgress:
case linphone::Call::State::OutgoingProgress:
qInfo() << QStringLiteral("Call transfer in progress.");
break;
// 3. Done.
case linphone::CallStateConnected:
case linphone::Call::State::Connected:
qInfo() << QStringLiteral("Call transfer succeeded.");
emit callTransferSucceeded(call);
break;
// 4. Error.
case linphone::CallStateEnd:
case linphone::CallStateError:
case linphone::Call::State::End:
case linphone::Call::State::Error:
qWarning() << QStringLiteral("Call transfer failed.");
emit callTransferFailed(call);
break;
@ -279,7 +282,7 @@ void CoreHandlers::onVersionUpdateCheckResultReceived (
const string &version,
const string &url
) {
if (result == linphone::VersionUpdateCheckResultNewVersionAvailable)
if (result == linphone::VersionUpdateCheckResult::NewVersionAvailable)
App::getInstance()->getNotifier()->notifyNewVersionAvailable(
Utils::coreStringToAppString(version),
Utils::coreStringToAppString(url)

View file

@ -43,12 +43,12 @@ public:
signals:
void authenticationRequested (const std::shared_ptr<linphone::AuthInfo> &authInfo);
void callEncryptionChanged (const std::shared_ptr<linphone::Call> &call);
void callStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::CallState state);
void callStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
void callTransferFailed (const std::shared_ptr<linphone::Call> &call);
void callTransferSucceeded (const std::shared_ptr<linphone::Call> &call);
void coreStarted ();
void isComposingChanged (const std::shared_ptr<linphone::ChatRoom> &chatRoom);
void logsUploadStateChanged (linphone::CoreLogCollectionUploadState state, const std::string &info);
void logsUploadStateChanged (linphone::Core::LogCollectionUploadState state, const std::string &info);
void messageReceived (const std::shared_ptr<linphone::ChatMessage> &message);
void presenceReceived (const QString &sipAddress, const std::shared_ptr<const linphone::PresenceModel> &presenceModel);
void registrationStateChanged (const std::shared_ptr<linphone::ProxyConfig> &proxyConfig, linphone::RegistrationState state);
@ -77,7 +77,7 @@ private:
void onCallStateChanged (
const std::shared_ptr<linphone::Core> &core,
const std::shared_ptr<linphone::Call> &call,
linphone::CallState state,
linphone::Call::State state,
const std::string &message
) override;
@ -100,7 +100,7 @@ private:
void onLogCollectionUploadStateChanged (
const std::shared_ptr<linphone::Core> &core,
linphone::CoreLogCollectionUploadState state,
linphone::Core::LogCollectionUploadState state,
const std::string &info
) override;
@ -138,7 +138,7 @@ private:
void onTransferStateChanged (
const std::shared_ptr<linphone::Core> &core,
const std::shared_ptr<linphone::Call> &call,
linphone::CallState state
linphone::Call::State state
) override;
void onVersionUpdateCheckResultReceived (

View file

@ -38,9 +38,9 @@
#include "utils/Utils.hpp"
#if defined(Q_OS_MACOS)
#include "messages-count-notifier/MessagesCountNotifierMacOs.hpp"
#include "messages-count-notifier/MessageCountNotifierMacOs.hpp"
#else
#include "messages-count-notifier/MessagesCountNotifierSystemTrayIcon.hpp"
#include "messages-count-notifier/MessageCountNotifierSystemTrayIcon.hpp"
#endif // if defined(Q_OS_MACOS)
#include "CoreHandlers.hpp"
@ -81,15 +81,21 @@ CoreManager::CoreManager (QObject *parent, const QString &configPath) :
CoreHandlers *coreHandlers = mHandlers.get();
QObject::connect(coreHandlers, &CoreHandlers::coreStarted, this, [] {
// Do not change this order. :) (Or pray.)
mInstance->mCallsListModel = new CallsListModel(mInstance);
mInstance->mContactsListModel = new ContactsListModel(mInstance);
mInstance->mSipAddressesModel = new SipAddressesModel(mInstance);
mInstance->mSettingsModel = new SettingsModel(mInstance);
mInstance->mAccountSettingsModel = new AccountSettingsModel(mInstance);
mInstance->mSettingsModel = new SettingsModel(mInstance);
mInstance->mSipAddressesModel = new SipAddressesModel(mInstance);
{
MessagesCountNotifier *messagesCountNotifier = new MessagesCountNotifier(mInstance);
messagesCountNotifier->updateUnreadMessagesCount();
MessageCountNotifier *messageCountNotifier = new MessageCountNotifier(mInstance);
messageCountNotifier->updateUnreadMessageCount();
QObject::connect(
messageCountNotifier, &MessageCountNotifier::unreadMessageCountChanged,
mInstance, &CoreManager::unreadMessageCountChanged
);
mInstance->mMessageCountNotifier = messageCountNotifier;
}
mInstance->migrate();
@ -108,21 +114,24 @@ CoreManager::CoreManager (QObject *parent, const QString &configPath) :
// -----------------------------------------------------------------------------
shared_ptr<ChatModel> CoreManager::getChatModelFromSipAddress (const QString &sipAddress) {
if (!sipAddress.length())
shared_ptr<ChatModel> CoreManager::getChatModel (const QString &peerAddress, const QString &localAddress) {
if (peerAddress.isEmpty() || localAddress.isEmpty())
return nullptr;
// Create a new chat model.
if (!mChatModels.contains(sipAddress)) {
Q_ASSERT(mCore->createAddress(Utils::appStringToCoreString(sipAddress)) != nullptr);
QPair<QString, QString> chatModelId{ peerAddress, localAddress };
if (!mChatModels.contains(chatModelId)) {
Q_ASSERT(mCore->createAddress(Utils::appStringToCoreString(peerAddress)));
Q_ASSERT(mCore->createAddress(Utils::appStringToCoreString(localAddress)));
auto deleter = [this](ChatModel *chatModel) {
mChatModels.remove(chatModel->getSipAddress());
auto deleter = [this, chatModelId](ChatModel *chatModel) {
bool removed = mChatModels.remove(chatModelId);
Q_ASSERT(removed);
delete chatModel;
};
shared_ptr<ChatModel> chatModel(new ChatModel(sipAddress), deleter);
mChatModels[chatModel->getSipAddress()] = chatModel;
shared_ptr<ChatModel> chatModel(new ChatModel(peerAddress, localAddress), deleter);
mChatModels[chatModelId] = chatModel;
emit chatModelCreated(chatModel);
@ -130,13 +139,13 @@ shared_ptr<ChatModel> CoreManager::getChatModelFromSipAddress (const QString &si
}
// Returns an existing chat model.
shared_ptr<ChatModel> chatModel = mChatModels[sipAddress].lock();
Q_CHECK_PTR(chatModel.get());
shared_ptr<ChatModel> chatModel = mChatModels[chatModelId].lock();
Q_CHECK_PTR(chatModel);
return chatModel;
}
bool CoreManager::chatModelExists (const QString &sipAddress) {
return mChatModels.contains(sipAddress);
bool CoreManager::chatModelExists (const QString &peerAddress, const QString &localAddress) {
return mChatModels.contains({ peerAddress, localAddress });
}
// -----------------------------------------------------------------------------
@ -204,7 +213,6 @@ void CoreManager::cleanLogs () const {
void CoreManager::setDatabasesPaths () {
SET_DATABASE_PATH(Friends, Paths::getFriendsListFilePath());
SET_DATABASE_PATH(CallLogs, Paths::getCallHistoryFilePath());
SET_DATABASE_PATH(Chat, Paths::getMessageHistoryFilePath());
}
#undef SET_DATABASE_PATH
@ -237,10 +245,11 @@ void CoreManager::createLinphoneCore (const QString &configPath) {
setResourcesPaths();
mCore = linphone::Factory::get()->createCore(
mHandlers,
Paths::getConfigFilePath(configPath),
Paths::getFactoryConfigFilePath()
Paths::getFactoryConfigFilePath(),
nullptr
);
mCore->addListener(mHandlers);
mCore->setVideoDisplayFilter("MSOGL");
mCore->usePreviewWindow(true);
@ -258,6 +267,8 @@ void CoreManager::createLinphoneCore (const QString &configPath) {
config->setInt("video", "display", 1);
}
mCore->start();
setDatabasesPaths();
setOtherPaths();
}
@ -295,6 +306,12 @@ QString CoreManager::getVersion () const {
// -----------------------------------------------------------------------------
int CoreManager::getUnreadMessageCount () const {
return mMessageCountNotifier ? mMessageCountNotifier->getUnreadMessageCount() : 0;
}
// -----------------------------------------------------------------------------
void CoreManager::iterate () {
mInstance->lockVideoRender();
mCore->iterate();
@ -303,13 +320,13 @@ void CoreManager::iterate () {
// -----------------------------------------------------------------------------
void CoreManager::handleLogsUploadStateChanged (linphone::CoreLogCollectionUploadState state, const string &info) {
void CoreManager::handleLogsUploadStateChanged (linphone::Core::LogCollectionUploadState state, const string &info) {
switch (state) {
case linphone::CoreLogCollectionUploadStateInProgress:
case linphone::Core::LogCollectionUploadState::InProgress:
break;
case linphone::CoreLogCollectionUploadStateDelivered:
case linphone::CoreLogCollectionUploadStateNotDelivered:
case linphone::Core::LogCollectionUploadState::Delivered:
case linphone::Core::LogCollectionUploadState::NotDelivered:
emit logsUploaded(Utils::coreStringToAppString(info));
break;
}

View file

@ -35,6 +35,7 @@ class CallsListModel;
class ChatModel;
class ContactsListModel;
class CoreHandlers;
class MessageCountNotifier;
class SettingsModel;
class SipAddressesModel;
class VcardModel;
@ -44,6 +45,7 @@ class CoreManager : public QObject {
Q_PROPERTY(QString version READ getVersion CONSTANT);
Q_PROPERTY(QString downloadUrl READ getDownloadUrl CONSTANT);
Q_PROPERTY(int unreadMessageCount READ getUnreadMessageCount NOTIFY unreadMessageCountChanged);
public:
bool started () const {
@ -60,8 +62,8 @@ public:
return mHandlers;
}
std::shared_ptr<ChatModel> getChatModelFromSipAddress (const QString &sipAddress);
bool chatModelExists (const QString &sipAddress);
std::shared_ptr<ChatModel> getChatModel (const QString &peerAddress, const QString &localAddress);
bool chatModelExists (const QString &sipAddress, const QString &localAddress);
// ---------------------------------------------------------------------------
// Video render lock.
@ -135,6 +137,8 @@ signals:
void logsUploaded (const QString &url);
void unreadMessageCountChanged (int count);
private:
CoreManager (QObject *parent, const QString &configPath);
@ -147,9 +151,11 @@ private:
QString getVersion () const;
int getUnreadMessageCount () const;
void iterate ();
void handleLogsUploadStateChanged (linphone::CoreLogCollectionUploadState state, const std::string &info);
void handleLogsUploadStateChanged (linphone::Core::LogCollectionUploadState state, const std::string &info);
static QString getDownloadUrl ();
@ -164,7 +170,9 @@ private:
SettingsModel *mSettingsModel = nullptr;
AccountSettingsModel *mAccountSettingsModel = nullptr;
QHash<QString, std::weak_ptr<ChatModel>> mChatModels;
MessageCountNotifier *mMessageCountNotifier = nullptr;
QHash<QPair<QString, QString>, std::weak_ptr<ChatModel>> mChatModels;
QTimer *mCbsTimer = nullptr;

View file

@ -1,5 +1,5 @@
/*
* AbstractMessagesCountNotifier.cpp
* AbstractMessageCountNotifier.cpp
* Copyright (C) 2017-2018 Belledonne Communications, Grenoble, France
*
* This program is free software; you can redistribute it and/or
@ -25,55 +25,48 @@
#include "components/core/CoreManager.hpp"
#include "components/settings/SettingsModel.hpp"
#include "AbstractMessagesCountNotifier.hpp"
#include "AbstractMessageCountNotifier.hpp"
// =============================================================================
using namespace std;
AbstractMessagesCountNotifier::AbstractMessagesCountNotifier (QObject *parent) : QObject(parent) {
AbstractMessageCountNotifier::AbstractMessageCountNotifier (QObject *parent) : QObject(parent) {
CoreManager *coreManager = CoreManager::getInstance();
QObject::connect(
coreManager, &CoreManager::chatModelCreated,
this, &AbstractMessagesCountNotifier::handleChatModelCreated
this, &AbstractMessageCountNotifier::handleChatModelCreated
);
QObject::connect(
coreManager->getHandlers().get(), &CoreHandlers::messageReceived,
this, &AbstractMessagesCountNotifier::handleMessageReceived
this, &AbstractMessageCountNotifier::updateUnreadMessageCount
);
QObject::connect(
coreManager->getSettingsModel(), &SettingsModel::chatEnabledChanged,
this, &AbstractMessagesCountNotifier::internalNotifyUnreadMessagesCount
this, &AbstractMessageCountNotifier::internalNotifyUnreadMessageCount
);
}
// -----------------------------------------------------------------------------
void AbstractMessagesCountNotifier::updateUnreadMessagesCount () {
mUnreadMessagesCount = 0;
for (const auto &chatRoom : CoreManager::getInstance()->getCore()->getChatRooms())
mUnreadMessagesCount += chatRoom->getUnreadMessagesCount();
internalNotifyUnreadMessagesCount();
void AbstractMessageCountNotifier::updateUnreadMessageCount () {
mUnreadMessageCount = CoreManager::getInstance()->getCore()->getUnreadChatMessageCountFromActiveLocals();
internalNotifyUnreadMessageCount();
}
void AbstractMessagesCountNotifier::internalNotifyUnreadMessagesCount () {
qInfo() << QStringLiteral("Notify unread messages count: %1.").arg(mUnreadMessagesCount);
int n = mUnreadMessagesCount > 99 ? 99 : mUnreadMessagesCount;
void AbstractMessageCountNotifier::internalNotifyUnreadMessageCount () {
qInfo() << QStringLiteral("Notify unread messages count: %1.").arg(mUnreadMessageCount);
int n = mUnreadMessageCount > 99 ? 99 : mUnreadMessageCount;
notifyUnreadMessagesCount(CoreManager::getInstance()->getSettingsModel()->getChatEnabled() ? n : 0);
notifyUnreadMessageCount(CoreManager::getInstance()->getSettingsModel()->getChatEnabled() ? n : 0);
unreadMessageCountChanged(mUnreadMessageCount);
}
// -----------------------------------------------------------------------------
void AbstractMessagesCountNotifier::handleChatModelCreated (const shared_ptr<ChatModel> &chatModel) {
void AbstractMessageCountNotifier::handleChatModelCreated (const shared_ptr<ChatModel> &chatModel) {
QObject::connect(
chatModel.get(), &ChatModel::messagesCountReset,
this, &AbstractMessagesCountNotifier::updateUnreadMessagesCount
chatModel.get(), &ChatModel::messageCountReset,
this, &AbstractMessageCountNotifier::updateUnreadMessageCount
);
}
void AbstractMessagesCountNotifier::handleMessageReceived (const shared_ptr<linphone::ChatMessage> &) {
mUnreadMessagesCount++;
internalNotifyUnreadMessagesCount();
}

View file

@ -1,5 +1,5 @@
/*
* AbstractMessagesCountNotifier.hpp
* AbstractMessageCountNotifier.hpp
* Copyright (C) 2017-2018 Belledonne Communications, Grenoble, France
*
* This program is free software; you can redistribute it and/or
@ -20,8 +20,8 @@
* Author: Ronan Abhamon
*/
#ifndef ABSTRACT_MESSAGES_COUNT_NOTIFIER_H_
#define ABSTRACT_MESSAGES_COUNT_NOTIFIER_H_
#ifndef ABSTRACT_MESSAGE_COUNT_NOTIFIER_H_
#define ABSTRACT_MESSAGE_COUNT_NOTIFIER_H_
#include <memory>
@ -35,24 +35,30 @@ namespace linphone {
class ChatModel;
class AbstractMessagesCountNotifier : public QObject {
class AbstractMessageCountNotifier : public QObject {
Q_OBJECT;
public:
AbstractMessagesCountNotifier (QObject *parent = Q_NULLPTR);
AbstractMessageCountNotifier (QObject *parent = Q_NULLPTR);
void updateUnreadMessagesCount ();
void updateUnreadMessageCount ();
int getUnreadMessageCount () const {
return mUnreadMessageCount;
}
signals:
void unreadMessageCountChanged (int count);
protected:
virtual void notifyUnreadMessagesCount (int n) = 0;
virtual void notifyUnreadMessageCount (int n) = 0;
private:
void internalNotifyUnreadMessagesCount ();
void internalNotifyUnreadMessageCount ();
void handleChatModelCreated (const std::shared_ptr<ChatModel> &chatModel);
void handleMessageReceived (const std::shared_ptr<linphone::ChatMessage> &message);
int mUnreadMessagesCount = 0;
int mUnreadMessageCount = 0;
};
#endif // ABSTRACT_MESSAGES_COUNT_NOTIFIER_H_
#endif // ABSTRACT_MESSAGE_COUNT_NOTIFIER_H_

View file

@ -1,5 +1,5 @@
/*
* MessagesCountNotifierMacOs.hpp
* MessageCountNotifierMacOs.hpp
* Copyright (C) 2017-2018 Belledonne Communications, Grenoble, France
*
* This program is free software; you can redistribute it and/or
@ -20,22 +20,22 @@
* Author: Ghislain MARY
*/
#ifndef MESSAGES_COUNT_NOTIFIER_MAC_OS_H_
#define MESSAGES_COUNT_NOTIFIER_MAC_OS_H_
#ifndef MESSAGE_COUNT_NOTIFIER_MAC_OS_H_
#define MESSAGE_COUNT_NOTIFIER_MAC_OS_H_
#include "AbstractMessagesCountNotifier.hpp"
#include "AbstractMessageCountNotifier.hpp"
// =============================================================================
extern "C" void notifyUnreadMessagesCountMacOs (int n);
extern "C" void notifyUnreadMessageCountMacOs (int n);
class MessagesCountNotifier : public AbstractMessagesCountNotifier {
class MessageCountNotifier : public AbstractMessageCountNotifier {
public:
MessagesCountNotifier (QObject *parent = Q_NULLPTR) : AbstractMessagesCountNotifier(parent) {}
MessageCountNotifier (QObject *parent = Q_NULLPTR) : AbstractMessageCountNotifier(parent) {}
void notifyUnreadMessagesCount (int n) override {
notifyUnreadMessagesCountMacOs(n);
void notifyUnreadMessageCount (int n) override {
notifyUnreadMessageCountMacOs(n);
}
};
#endif // MESSAGES_COUNT_NOTIFIER_MAC_OS_H_
#endif // MESSAGE_COUNT_NOTIFIER_MAC_OS_H_

View file

@ -1,5 +1,5 @@
/*
* MessagesCountNotifierMacOS.m
* MessageCountNotifierMacOS.m
* Copyright (C) 2017-2018 Belledonne Communications, Grenoble, France
*
* This program is free software; you can redistribute it and/or
@ -24,7 +24,7 @@
// =============================================================================
void notifyUnreadMessagesCountMacOs (int n) {
void notifyUnreadMessageCountMacOs (int n) {
NSString *badgeStr = (n > 0) ? [NSString stringWithFormat:@"%d", n] : @"";
[[NSApp dockTile] setBadgeLabel:badgeStr];
}

View file

@ -1,5 +1,5 @@
/*
* MessagesCountNotifierSystemTrayIcon.hpp
* MessageCountNotifierSystemTrayIcon.hpp
* Copyright (C) 2017-2018 Belledonne Communications, Grenoble, France
*
* This program is free software; you can redistribute it and/or
@ -31,7 +31,7 @@
#include "utils/LinphoneUtils.hpp"
#include "utils/Utils.hpp"
#include "MessagesCountNotifierSystemTrayIcon.hpp"
#include "MessageCountNotifierSystemTrayIcon.hpp"
// =============================================================================
@ -46,7 +46,7 @@ namespace {
constexpr int IconCounterTextPixelSize = 144;
}
MessagesCountNotifier::MessagesCountNotifier (QObject *parent) : AbstractMessagesCountNotifier(parent) {
MessageCountNotifier::MessageCountNotifier (QObject *parent) : AbstractMessageCountNotifier(parent) {
QSvgRenderer renderer((QString(LinphoneUtils::WindowIconPath)));
if (!renderer.isValid())
qFatal("Invalid SVG Image.");
@ -62,20 +62,20 @@ MessagesCountNotifier::MessagesCountNotifier (QObject *parent) : AbstractMessage
mBlinkTimer = new QTimer(this);
mBlinkTimer->setInterval(IconCounterBlinkInterval);
QObject::connect(mBlinkTimer, &QTimer::timeout, this, &MessagesCountNotifier::update);
QObject::connect(mBlinkTimer, &QTimer::timeout, this, &MessageCountNotifier::update);
Utils::connectOnce(
App::getInstance(), &App::focusWindowChanged,
this, &MessagesCountNotifier::updateUnreadMessagesCount
this, &MessageCountNotifier::updateUnreadMessageCount
);
}
MessagesCountNotifier::~MessagesCountNotifier () {
MessageCountNotifier::~MessageCountNotifier () {
delete mBuf;
delete mBufWithCounter;
}
void MessagesCountNotifier::notifyUnreadMessagesCount (int n) {
void MessageCountNotifier::notifyUnreadMessageCount (int n) {
QSystemTrayIcon *sysTrayIcon = App::getInstance()->getSystemTrayIcon();
if (!sysTrayIcon)
return;
@ -115,7 +115,7 @@ void MessagesCountNotifier::notifyUnreadMessagesCount (int n) {
update();
}
void MessagesCountNotifier::update () {
void MessageCountNotifier::update () {
QSystemTrayIcon *sysTrayIcon = App::getInstance()->getSystemTrayIcon();
Q_CHECK_PTR(sysTrayIcon);
sysTrayIcon->setIcon(QIcon(mDisplayCounter ? *mBufWithCounter : *mBuf));

View file

@ -1,5 +1,5 @@
/*
* MessagesCountNotifierSystemTrayIcon.hpp
* MessageCountNotifierSystemTrayIcon.hpp
* Copyright (C) 2017-2018 Belledonne Communications, Grenoble, France
*
* This program is free software; you can redistribute it and/or
@ -20,22 +20,22 @@
* Author: Ronan Abhamon
*/
#ifndef MESSAGES_COUNT_NOTIFIER_SYSTEM_TRAY_ICON_H_
#define MESSAGES_COUNT_NOTIFIER_SYSTEM_TRAY_ICON_H_
#ifndef MESSAGE_COUNT_NOTIFIER_SYSTEM_TRAY_ICON_H_
#define MESSAGE_COUNT_NOTIFIER_SYSTEM_TRAY_ICON_H_
#include "AbstractMessagesCountNotifier.hpp"
#include "AbstractMessageCountNotifier.hpp"
// =============================================================================
class QTimer;
class MessagesCountNotifier : public AbstractMessagesCountNotifier {
class MessageCountNotifier : public AbstractMessageCountNotifier {
public:
MessagesCountNotifier (QObject *parent = Q_NULLPTR);
~MessagesCountNotifier ();
MessageCountNotifier (QObject *parent = Q_NULLPTR);
~MessageCountNotifier ();
protected:
void notifyUnreadMessagesCount (int n) override;
void notifyUnreadMessageCount (int n) override;
private:
void update ();
@ -46,4 +46,4 @@ private:
bool mDisplayCounter = false;
};
#endif // MESSAGES_COUNT_NOTIFIER_SYSTEM_TRAY_ICON_H_
#endif // MESSAGE_COUNT_NOTIFIER_SYSTEM_TRAY_ICON_H_

View file

@ -237,7 +237,9 @@ void Notifier::notifyReceivedMessage (const shared_ptr<linphone::ChatMessage> &m
? tr("newFileMessage")
: Utils::coreStringToAppString(message->getText());
map["sipAddress"] = Utils::coreStringToAppString(message->getFromAddress()->asStringUriOnly());
shared_ptr<linphone::ChatRoom> chatRoom(message->getChatRoom());
map["peerAddress"] = Utils::coreStringToAppString(chatRoom->getPeerAddress()->asStringUriOnly());
map["localAddress"] = Utils::coreStringToAppString(chatRoom->getLocalAddress()->asStringUriOnly());
map["window"].setValue(App::getInstance()->getMainWindow());
SHOW_NOTIFICATION(map);

View file

@ -36,10 +36,10 @@ class Presence : public QObject {
public:
enum PresenceStatus {
Online = linphone::ConsolidatedPresenceOnline,
Busy = linphone::ConsolidatedPresenceBusy,
DoNotDisturb = linphone::ConsolidatedPresenceDoNotDisturb,
Offline = linphone::ConsolidatedPresenceOffline
Online = int(linphone::ConsolidatedPresence::Online),
Busy = int(linphone::ConsolidatedPresence::Busy),
DoNotDisturb = int(linphone::ConsolidatedPresence::DoNotDisturb),
Offline = int(linphone::ConsolidatedPresence::Offline)
};
Q_ENUM(PresenceStatus);

View file

@ -36,15 +36,15 @@ using namespace std;
static inline AccountSettingsModel::RegistrationState mapLinphoneRegistrationStateToUi (linphone::RegistrationState state) {
switch (state) {
case linphone::RegistrationStateNone:
case linphone::RegistrationStateCleared:
case linphone::RegistrationStateFailed:
case linphone::RegistrationState::None:
case linphone::RegistrationState::Cleared:
case linphone::RegistrationState::Failed:
return AccountSettingsModel::RegistrationStateNotRegistered;
case linphone::RegistrationStateProgress:
case linphone::RegistrationState::Progress:
return AccountSettingsModel::RegistrationStateInProgress;
case linphone::RegistrationStateOk:
case linphone::RegistrationState::Ok:
break;
}
@ -54,10 +54,12 @@ static inline AccountSettingsModel::RegistrationState mapLinphoneRegistrationSta
// -----------------------------------------------------------------------------
AccountSettingsModel::AccountSettingsModel (QObject *parent) : QObject(parent) {
CoreManager *coreManager = CoreManager::getInstance();
QObject::connect(
CoreManager::getInstance()->getHandlers().get(), &CoreHandlers::registrationStateChanged,
coreManager->getHandlers().get(), &CoreHandlers::registrationStateChanged,
this, &AccountSettingsModel::handleRegistrationStateChanged
);
QObject::connect(coreManager, &CoreManager::unreadMessageCountChanged, this, [this]() { emit accountSettingsUpdated(); });
}
// -----------------------------------------------------------------------------
@ -76,6 +78,10 @@ void AccountSettingsModel::setUsedSipAddress (const shared_ptr<const linphone::A
proxyConfig ? proxyConfig->setIdentityAddress(address) : core->setPrimaryContact(address->asString());
}
QString AccountSettingsModel::getUsedSipAddressAsString () const {
return Utils::coreStringToAppString(getUsedSipAddress()->asStringUriOnly());
}
// -----------------------------------------------------------------------------
bool AccountSettingsModel::addOrUpdateProxyConfig (const shared_ptr<linphone::ProxyConfig> &proxyConfig) {
@ -124,7 +130,7 @@ QVariantMap AccountSettingsModel::getProxyConfigDescription (const shared_ptr<li
map["avpfInterval"] = proxyConfig->getAvpfRrInterval();
map["registerEnabled"] = proxyConfig->registerEnabled();
map["publishPresence"] = proxyConfig->publishEnabled();
map["avpfEnabled"] = proxyConfig->getAvpfMode() == linphone::AVPFMode::AVPFModeEnabled;
map["avpfEnabled"] = proxyConfig->getAvpfMode() == linphone::AVPFMode::Enabled;
map["registrationState"] = mapLinphoneRegistrationStateToUi(proxyConfig->getState());
shared_ptr<linphone::NatPolicy> natPolicy = proxyConfig->getNatPolicy();
@ -135,14 +141,33 @@ QVariantMap AccountSettingsModel::getProxyConfigDescription (const shared_ptr<li
map["stunServer"] = Utils::coreStringToAppString(natPolicy->getStunServer());
map["turnUser"] = Utils::coreStringToAppString(natPolicy->getStunServerUsername());
shared_ptr<const linphone::AuthInfo> authInfo = proxyConfig->findAuthInfo();
map["turnPassword"] = authInfo ? Utils::coreStringToAppString(authInfo->getPasswd()) : QString("");
map["turnPassword"] = authInfo ? Utils::coreStringToAppString(authInfo->getPassword()) : QString("");
return map;
}
void AccountSettingsModel::setDefaultProxyConfig (const shared_ptr<linphone::ProxyConfig> &proxyConfig) {
CoreManager::getInstance()->getCore()->setDefaultProxyConfig(proxyConfig);
emit accountSettingsUpdated();
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
if (core->getDefaultProxyConfig() != proxyConfig) {
core->setDefaultProxyConfig(proxyConfig);
emit accountSettingsUpdated();
}
}
void AccountSettingsModel::setDefaultProxyConfigFromSipAddress (const QString &sipAddress) {
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
if (Utils::coreStringToAppString(core->getPrimaryContactParsed()->asStringUriOnly()) == sipAddress) {
setDefaultProxyConfig(nullptr);
return;
}
for (const auto &proxyConfig : core->getProxyConfigList())
if (Utils::coreStringToAppString(proxyConfig->getIdentityAddress()->asStringUriOnly()) == sipAddress) {
setDefaultProxyConfig(proxyConfig);
return;
}
qWarning() << "Unable to set default proxy config from:" << sipAddress;
}
void AccountSettingsModel::removeProxyConfig (const shared_ptr<linphone::ProxyConfig> &proxyConfig) {
@ -197,8 +222,8 @@ bool AccountSettingsModel::addOrUpdateProxyConfig (
proxyConfig->enableRegister(data["registerEnabled"].toBool());
proxyConfig->enablePublish(data["publishPresence"].toBool());
proxyConfig->setAvpfMode(data["avpfEnabled"].toBool()
? linphone::AVPFMode::AVPFModeEnabled
: linphone::AVPFMode::AVPFModeDefault
? linphone::AVPFMode::Enabled
: linphone::AVPFMode::Default
);
shared_ptr<linphone::NatPolicy> natPolicy = proxyConfig->getNatPolicy();
@ -214,7 +239,7 @@ bool AccountSettingsModel::addOrUpdateProxyConfig (
shared_ptr<linphone::Core> core = proxyConfig->getCore();
if (authInfo) {
shared_ptr<linphone::AuthInfo> clonedAuthInfo = authInfo->clone();
clonedAuthInfo->setPasswd(Utils::appStringToCoreString(data["turnPassword"].toString()));
clonedAuthInfo->setPassword(Utils::appStringToCoreString(data["turnPassword"].toString()));
core->removeAuthInfo(authInfo);
core->addAuthInfo(clonedAuthInfo);
@ -248,7 +273,7 @@ void AccountSettingsModel::addAuthInfo (
const QString &password,
const QString &userId
) {
authInfo->setPasswd(Utils::appStringToCoreString(password));
authInfo->setPassword(Utils::appStringToCoreString(password));
authInfo->setUserid(Utils::appStringToCoreString(userId));
CoreManager::getInstance()->getCore()->addAuthInfo(authInfo);
@ -283,10 +308,6 @@ void AccountSettingsModel::setUsername (const QString &username) {
emit accountSettingsUpdated();
}
QString AccountSettingsModel::getSipAddress () const {
return Utils::coreStringToAppString(getUsedSipAddress()->asStringUriOnly());
}
AccountSettingsModel::RegistrationState AccountSettingsModel::getRegistrationState () const {
shared_ptr<linphone::ProxyConfig> proxyConfig = CoreManager::getInstance()->getCore()->getDefaultProxyConfig();
return proxyConfig ? mapLinphoneRegistrationStateToUi(proxyConfig->getState()) : RegistrationStateNotRegistered;
@ -343,6 +364,7 @@ QVariantList AccountSettingsModel::getAccounts () const {
{
QVariantMap account;
account["sipAddress"] = Utils::coreStringToAppString(core->getPrimaryContactParsed()->asStringUriOnly());
account["unreadMessageCount"] = core->getUnreadChatMessageCountFromLocal(core->getPrimaryContactParsed());
accounts << account;
}
@ -350,6 +372,7 @@ QVariantList AccountSettingsModel::getAccounts () const {
QVariantMap account;
account["sipAddress"] = Utils::coreStringToAppString(proxyConfig->getIdentityAddress()->asStringUriOnly());
account["proxyConfig"].setValue(proxyConfig);
account["unreadMessageCount"] = proxyConfig->getUnreadChatMessageCount();
accounts << account;
}

View file

@ -33,7 +33,7 @@ class AccountSettingsModel : public QObject {
// Selected proxy config.
Q_PROPERTY(QString username READ getUsername WRITE setUsername NOTIFY accountSettingsUpdated);
Q_PROPERTY(QString sipAddress READ getSipAddress NOTIFY accountSettingsUpdated);
Q_PROPERTY(QString sipAddress READ getUsedSipAddressAsString NOTIFY accountSettingsUpdated);
Q_PROPERTY(RegistrationState registrationState READ getRegistrationState NOTIFY accountSettingsUpdated);
// Default info.
@ -56,11 +56,14 @@ public:
std::shared_ptr<const linphone::Address> getUsedSipAddress () const;
void setUsedSipAddress (const std::shared_ptr<const linphone::Address> &address);
QString getUsedSipAddressAsString () const;
bool addOrUpdateProxyConfig (const std::shared_ptr<linphone::ProxyConfig> &proxyConfig);
Q_INVOKABLE QVariantMap getProxyConfigDescription (const std::shared_ptr<linphone::ProxyConfig> &proxyConfig);
Q_INVOKABLE void setDefaultProxyConfig (const std::shared_ptr<linphone::ProxyConfig> &proxyConfig);
Q_INVOKABLE void setDefaultProxyConfigFromSipAddress (const QString &sipAddress);
Q_INVOKABLE bool addOrUpdateProxyConfig (const std::shared_ptr<linphone::ProxyConfig> &proxyConfig, const QVariantMap &data);
Q_INVOKABLE void removeProxyConfig (const std::shared_ptr<linphone::ProxyConfig> &proxyConfig);
@ -82,8 +85,6 @@ private:
QString getUsername () const;
void setUsername (const QString &username);
QString getSipAddress () const;
RegistrationState getRegistrationState () const;
// ---------------------------------------------------------------------------

View file

@ -104,7 +104,7 @@ QStringList SettingsModel::getCaptureDevices () const {
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
QStringList list;
for (const auto &device : core->getSoundDevices()) {
for (const auto &device : core->getSoundDevicesList()) {
if (core->soundDeviceCanCapture(device))
list << Utils::coreStringToAppString(device);
}
@ -116,7 +116,7 @@ QStringList SettingsModel::getPlaybackDevices () const {
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
QStringList list;
for (const auto &device : core->getSoundDevices())
for (const auto &device : core->getSoundDevicesList())
if (core->soundDeviceCanPlayback(device))
list << Utils::coreStringToAppString(device);
@ -213,7 +213,7 @@ void SettingsModel::setShowAudioCodecs (bool status) {
QStringList SettingsModel::getVideoDevices () const {
QStringList list;
for (const auto &device : CoreManager::getInstance()->getCore()->getVideoDevices())
for (const auto &device : CoreManager::getInstance()->getCore()->getVideoDevicesList())
list << Utils::coreStringToAppString(device);
return list;
@ -504,13 +504,13 @@ QVariantList SettingsModel::getSupportedMediaEncryptions () const {
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
QVariantList list;
if (core->mediaEncryptionSupported(linphone::MediaEncryptionDTLS))
if (core->mediaEncryptionSupported(linphone::MediaEncryption::DTLS))
list << buildEncryptionDescription(MediaEncryptionDtls, "DTLS");
if (core->mediaEncryptionSupported(linphone::MediaEncryptionSRTP))
if (core->mediaEncryptionSupported(linphone::MediaEncryption::SRTP))
list << buildEncryptionDescription(MediaEncryptionSrtp, "SRTP");
if (core->mediaEncryptionSupported(linphone::MediaEncryptionZRTP))
if (core->mediaEncryptionSupported(linphone::MediaEncryption::ZRTP))
list << buildEncryptionDescription(MediaEncryptionZrtp, "ZRTP");
return list;
@ -803,7 +803,7 @@ QString SettingsModel::getTurnPassword () const {
shared_ptr<linphone::NatPolicy> natPolicy = core->getNatPolicy();
shared_ptr<const linphone::AuthInfo> authInfo = core->findAuthInfo(natPolicy->getStunServerUsername(), "", "");
return authInfo ? Utils::coreStringToAppString(authInfo->getPasswd()) : QString("");
return authInfo ? Utils::coreStringToAppString(authInfo->getPassword()) : QString("");
}
void SettingsModel::setTurnPassword (const QString &password) {
@ -815,7 +815,7 @@ void SettingsModel::setTurnPassword (const QString &password) {
if (authInfo) {
shared_ptr<linphone::AuthInfo> clonedAuthInfo = authInfo->clone();
clonedAuthInfo->setPasswd(Utils::appStringToCoreString(password));
clonedAuthInfo->setPassword(Utils::appStringToCoreString(password));
core->removeAuthInfo(authInfo);
core->addAuthInfo(clonedAuthInfo);

View file

@ -171,17 +171,17 @@ class SettingsModel : public QObject {
public:
enum MediaEncryption {
MediaEncryptionNone = linphone::MediaEncryptionNone,
MediaEncryptionDtls = linphone::MediaEncryptionDTLS,
MediaEncryptionSrtp = linphone::MediaEncryptionSRTP,
MediaEncryptionZrtp = linphone::MediaEncryptionZRTP
MediaEncryptionNone = int(linphone::MediaEncryption::None),
MediaEncryptionDtls = int(linphone::MediaEncryption::DTLS),
MediaEncryptionSrtp = int(linphone::MediaEncryption::SRTP),
MediaEncryptionZrtp = int(linphone::MediaEncryption::ZRTP)
};
Q_ENUM(MediaEncryption);
enum LimeState {
LimeStateDisabled = linphone::LimeStateDisabled,
LimeStateMandatory = linphone::LimeStateMandatory,
LimeStatePreferred = linphone::LimeStatePreferred
LimeStateDisabled = int(linphone::LimeState::Disabled),
LimeStateMandatory = int(linphone::LimeState::Mandatory),
LimeStatePreferred = int(linphone::LimeState::Preferred)
};
Q_ENUM(LimeState);

View file

@ -24,8 +24,9 @@
// =============================================================================
SipAddressObserver::SipAddressObserver (const QString &sipAddress) {
mSipAddress = sipAddress;
SipAddressObserver::SipAddressObserver (const QString &peerAddress, const QString &localAddress) {
mPeerAddress = peerAddress;
mLocalAddress = localAddress;
}
void SipAddressObserver::setContact (ContactModel *contact) {
@ -44,10 +45,10 @@ void SipAddressObserver::setPresenceStatus (const Presence::PresenceStatus &pres
emit presenceStatusChanged(presenceStatus);
}
void SipAddressObserver::setUnreadMessagesCount (int unreadMessagesCount) {
if (unreadMessagesCount == mUnreadMessagesCount)
void SipAddressObserver::setUnreadMessageCount (int unreadMessageCount) {
if (unreadMessageCount == mUnreadMessageCount)
return;
mUnreadMessagesCount = unreadMessagesCount;
emit unreadMessagesCountChanged(unreadMessagesCount);
mUnreadMessageCount = unreadMessageCount;
emit unreadMessageCountChanged(unreadMessageCount);
}

View file

@ -34,23 +34,28 @@ class SipAddressObserver : public QObject {
Q_OBJECT;
Q_PROPERTY(QString sipAddress READ getSipAddress CONSTANT);
Q_PROPERTY(QString peerAddress READ getPeerAddress CONSTANT);
Q_PROPERTY(QString localAddress READ getLocalAddress CONSTANT);
Q_PROPERTY(ContactModel * contact READ getContact NOTIFY contactChanged);
Q_PROPERTY(ContactModel *contact READ getContact NOTIFY contactChanged);
Q_PROPERTY(Presence::PresenceStatus presenceStatus READ getPresenceStatus NOTIFY presenceStatusChanged);
Q_PROPERTY(int unreadMessagesCount READ getUnreadMessagesCount NOTIFY unreadMessagesCountChanged);
Q_PROPERTY(int unreadMessageCount READ getUnreadMessageCount NOTIFY unreadMessageCountChanged);
public:
SipAddressObserver (const QString &sipAddress);
SipAddressObserver (const QString &peerAddress, const QString &localAddress);
signals:
void contactChanged (ContactModel *contact);
void presenceStatusChanged (const Presence::PresenceStatus &presenceStatus);
void unreadMessagesCountChanged (int unreadMessagesCount);
void unreadMessageCountChanged (int unreadMessageCount);
private:
QString getSipAddress () const {
return mSipAddress;
QString getPeerAddress () const {
return mPeerAddress;
}
QString getLocalAddress () const {
return mLocalAddress;
}
// ---------------------------------------------------------------------------
@ -71,17 +76,18 @@ private:
// ---------------------------------------------------------------------------
int getUnreadMessagesCount () const {
return mUnreadMessagesCount;
int getUnreadMessageCount () const {
return mUnreadMessageCount;
}
void setUnreadMessagesCount (int unreadMessagesCount);
void setUnreadMessageCount (int unreadMessageCount);
QString mSipAddress;
QString mPeerAddress;
QString mLocalAddress;
ContactModel *mContact = nullptr;
Presence::PresenceStatus mPresenceStatus = Presence::PresenceStatus::Offline;
int mUnreadMessagesCount = 0;
int mUnreadMessageCount = 0;
};
Q_DECLARE_METATYPE(SipAddressObserver *);

View file

@ -21,6 +21,7 @@
*/
#include <QDateTime>
#include <QElapsedTimer>
#include <QUrl>
#include "components/call/CallModel.hpp"
@ -30,6 +31,7 @@
#include "components/contacts/ContactsListModel.hpp"
#include "components/core/CoreHandlers.hpp"
#include "components/core/CoreManager.hpp"
#include "components/settings/AccountSettingsModel.hpp"
#include "utils/LinphoneUtils.hpp"
#include "utils/Utils.hpp"
@ -39,6 +41,17 @@
using namespace std;
// -----------------------------------------------------------------------------
static inline QVariantMap buildVariantMap (const SipAddressesModel::SipAddressEntry &sipAddressEntry) {
return QVariantMap{
{ "sipAddress", sipAddressEntry.sipAddress },
{ "contact", QVariant::fromValue(sipAddressEntry.contact) },
{ "presenceStatus", sipAddressEntry.presenceStatus },
{ "__localToConferenceEntry", QVariant::fromValue(&sipAddressEntry.localAddressToConferenceEntry) }
};
}
SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(parent) {
initSipAddresses();
@ -58,7 +71,7 @@ SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(pare
QObject::connect(coreHandlers, &CoreHandlers::messageReceived, this, &SipAddressesModel::handleMessageReceived);
QObject::connect(coreHandlers, &CoreHandlers::callStateChanged, this, &SipAddressesModel::handleCallStateChanged);
QObject::connect(coreHandlers, &CoreHandlers::presenceReceived, this, &SipAddressesModel::handlePresenceReceived);
QObject::connect(coreHandlers, &CoreHandlers::isComposingChanged, this, &SipAddressesModel::handlerIsComposingChanged);
QObject::connect(coreHandlers, &CoreHandlers::isComposingChanged, this, &SipAddressesModel::handleIsComposingChanged);
}
// -----------------------------------------------------------------------------
@ -80,7 +93,7 @@ QVariant SipAddressesModel::data (const QModelIndex &index, int role) const {
return QVariant();
if (role == Qt::DisplayRole)
return QVariant::fromValue(*mRefs[row]);
return buildVariantMap(*mRefs[row]);
return QVariant();
}
@ -88,44 +101,43 @@ QVariant SipAddressesModel::data (const QModelIndex &index, int role) const {
// -----------------------------------------------------------------------------
QVariantMap SipAddressesModel::find (const QString &sipAddress) const {
auto it = mSipAddresses.find(sipAddress);
return it == mSipAddresses.end() ? QVariantMap() : *it;
auto it = mPeerAddressToSipAddressEntry.find(sipAddress);
if (it == mPeerAddressToSipAddressEntry.end())
return QVariantMap();
return buildVariantMap(*it);
}
// -----------------------------------------------------------------------------
ContactModel *SipAddressesModel::mapSipAddressToContact (const QString &sipAddress) const {
auto it = mSipAddresses.find(sipAddress);
if (it == mSipAddresses.end())
return nullptr;
return it->value("contact").value<ContactModel *>();
auto it = mPeerAddressToSipAddressEntry.find(sipAddress);
return it == mPeerAddressToSipAddressEntry.end() ? nullptr : it->contact;
}
// -----------------------------------------------------------------------------
SipAddressObserver *SipAddressesModel::getSipAddressObserver (const QString &sipAddress) {
SipAddressObserver *model = new SipAddressObserver(sipAddress);
const QString cleanedSipAddress = cleanSipAddress(sipAddress);
SipAddressObserver *SipAddressesModel::getSipAddressObserver (const QString &peerAddress, const QString &localAddress) {
SipAddressObserver *model = new SipAddressObserver(peerAddress, localAddress);
const QString cleanedPeerAddress = cleanSipAddress(peerAddress);
const QString cleanedLocalAddress = cleanSipAddress(localAddress);
{
auto it = mSipAddresses.find(cleanedSipAddress);
if (it != mSipAddresses.end()) {
model->setContact(it->value("contact").value<ContactModel *>());
model->setPresenceStatus(
it->value("presenceStatus", Presence::PresenceStatus::Offline).value<Presence::PresenceStatus>()
);
model->setUnreadMessagesCount(
it->value("unreadMessagesCount", 0).toInt()
);
}
auto it = mPeerAddressToSipAddressEntry.find(cleanedPeerAddress);
if (it != mPeerAddressToSipAddressEntry.end()) {
model->setContact(it->contact);
model->setPresenceStatus(it->presenceStatus);
auto it2 = it->localAddressToConferenceEntry.find(cleanedLocalAddress);
if (it2 != it->localAddressToConferenceEntry.end())
model->setUnreadMessageCount(it2->unreadMessageCount);
}
mObservers.insert(cleanedSipAddress, model);
QObject::connect(model, &SipAddressObserver::destroyed, this, [this, model, cleanedSipAddress]() {
// Do not use `model` methods here. `model` is partially destroyed here!
if (mObservers.remove(cleanedSipAddress, model) == 0)
qWarning() << QStringLiteral("Unable to remove sip address `%1` from observers.").arg(cleanedSipAddress);
mObservers.insert(cleanedPeerAddress, model);
QObject::connect(model, &SipAddressObserver::destroyed, this, [this, model, cleanedPeerAddress, cleanedLocalAddress]() {
// Do not use `model` methods. `model` is partially destroyed here!
if (mObservers.remove(cleanedPeerAddress, model) == 0)
qWarning() << QStringLiteral("Unable to remove (%1, %2) from observers.")
.arg(cleanedPeerAddress).arg(cleanedLocalAddress);
});
return model;
@ -133,7 +145,7 @@ SipAddressObserver *SipAddressesModel::getSipAddressObserver (const QString &sip
// -----------------------------------------------------------------------------
QString SipAddressesModel::getTransportFromSipAddress (const QString &sipAddress) const {
QString SipAddressesModel::getTransportFromSipAddress (const QString &sipAddress) {
const shared_ptr<const linphone::Address> address = linphone::Factory::get()->createAddress(
Utils::appStringToCoreString(sipAddress)
);
@ -142,20 +154,20 @@ QString SipAddressesModel::getTransportFromSipAddress (const QString &sipAddress
return QString("");
switch (address->getTransport()) {
case linphone::TransportTypeUdp:
case linphone::TransportType::Udp:
return QStringLiteral("UDP");
case linphone::TransportTypeTcp:
case linphone::TransportType::Tcp:
return QStringLiteral("TCP");
case linphone::TransportTypeTls:
case linphone::TransportType::Tls:
return QStringLiteral("TLS");
case linphone::TransportTypeDtls:
case linphone::TransportType::Dtls:
return QStringLiteral("DTLS");
}
return QString("");
}
QString SipAddressesModel::addTransportToSipAddress (const QString &sipAddress, const QString &transport) const {
QString SipAddressesModel::addTransportToSipAddress (const QString &sipAddress, const QString &transport) {
shared_ptr<linphone::Address> address = linphone::Factory::get()->createAddress(
Utils::appStringToCoreString(sipAddress)
);
@ -213,18 +225,13 @@ bool SipAddressesModel::removeRow (int row, const QModelIndex &parent) {
bool SipAddressesModel::removeRows (int row, int count, const QModelIndex &parent) {
int limit = row + count - 1;
if (row < 0 || count < 0 || limit >= mSipAddresses.count())
if (row < 0 || count < 0 || limit >= mRefs.count())
return false;
beginRemoveRows(parent, row, limit);
for (int i = 0; i < count; ++i) {
const QVariantMap *map = mRefs.takeAt(row);
QString sipAddress = (*map)["sipAddress"].toString();
qInfo() << QStringLiteral("Remove sip address: `%1`.").arg(sipAddress);
mSipAddresses.remove(sipAddress);
}
for (int i = 0; i < count; ++i)
mPeerAddressToSipAddressEntry.remove(mRefs.takeAt(row)->sipAddress);
endRemoveRows();
@ -242,8 +249,8 @@ void SipAddressesModel::handleChatModelCreated (const shared_ptr<ChatModel> &cha
QObject::connect(ptr, &ChatModel::lastEntryRemoved, this, [this, ptr] {
handleLastEntryRemoved(ptr);
});
QObject::connect(ptr, &ChatModel::messagesCountReset, this, [this, ptr] {
handleMessagesCountReset(ptr);
QObject::connect(ptr, &ChatModel::messageCountReset, this, [this, ptr] {
handleMessageCountReset(ptr);
});
QObject::connect(ptr, &ChatModel::messageSent, this, &SipAddressesModel::handleMessageSent);
@ -280,19 +287,20 @@ void SipAddressesModel::handleSipAddressRemoved (ContactModel *contact, const QS
}
void SipAddressesModel::handleMessageReceived (const shared_ptr<linphone::ChatMessage> &message) {
const QString sipAddress = Utils::coreStringToAppString(message->getFromAddress()->asStringUriOnly());
addOrUpdateSipAddress(sipAddress, message);
qInfo() << "Handle message received.";
const QString peerAddress(Utils::coreStringToAppString(message->getChatRoom()->getPeerAddress()->asStringUriOnly()));
addOrUpdateSipAddress(peerAddress, message);
}
void SipAddressesModel::handleCallStateChanged (
const shared_ptr<linphone::Call> &call,
linphone::CallState state
linphone::Call::State state
) {
// Ignore aborted calls.
if (call->getCallLog()->getStatus() == linphone::CallStatus::CallStatusAborted)
if (call->getCallLog()->getStatus() == linphone::Call::Status::Aborted)
return;
if (state == linphone::CallStateEnd || state == linphone::CallStateError)
if (state == linphone::Call::State::End || state == linphone::Call::State::Error)
addOrUpdateSipAddress(
Utils::coreStringToAppString(call->getRemoteAddress()->asStringUriOnly()), call
);
@ -305,24 +313,24 @@ void SipAddressesModel::handlePresenceReceived (
Presence::PresenceStatus status;
switch (presenceModel->getConsolidatedPresence()) {
case linphone::ConsolidatedPresenceOnline:
case linphone::ConsolidatedPresence::Online:
status = Presence::PresenceStatus::Online;
break;
case linphone::ConsolidatedPresenceBusy:
case linphone::ConsolidatedPresence::Busy:
status = Presence::PresenceStatus::Busy;
break;
case linphone::ConsolidatedPresenceDoNotDisturb:
case linphone::ConsolidatedPresence::DoNotDisturb:
status = Presence::PresenceStatus::DoNotDisturb;
break;
case linphone::ConsolidatedPresenceOffline:
case linphone::ConsolidatedPresence::Offline:
status = Presence::PresenceStatus::Offline;
break;
}
auto it = mSipAddresses.find(sipAddress);
if (it != mSipAddresses.end()) {
auto it = mPeerAddressToSipAddressEntry.find(sipAddress);
if (it != mPeerAddressToSipAddressEntry.end()) {
qInfo() << QStringLiteral("Update presence of `%1`: %2.").arg(sipAddress).arg(status);
(*it)["presenceStatus"] = status;
it->presenceStatus = status;
int row = mRefs.indexOf(&(*it));
Q_ASSERT(row != -1);
@ -333,26 +341,34 @@ void SipAddressesModel::handlePresenceReceived (
}
void SipAddressesModel::handleAllEntriesRemoved (ChatModel *chatModel) {
auto it = mSipAddresses.find(chatModel->getSipAddress());
if (it == mSipAddresses.end())
auto it = mPeerAddressToSipAddressEntry.find(chatModel->getPeerAddress());
if (it == mPeerAddressToSipAddressEntry.end())
return;
auto it2 = it->localAddressToConferenceEntry.find(chatModel->getLocalAddress());
if (it2 == it->localAddressToConferenceEntry.end())
return;
it->localAddressToConferenceEntry.erase(it2);
int row = mRefs.indexOf(&(*it));
Q_ASSERT(row != -1);
// No history, no contact => Remove sip address from list.
if (!it->contains("contact")) {
if (!it->contact && it->localAddressToConferenceEntry.empty()) {
removeRow(row);
return;
}
it->remove("timestamp");
emit dataChanged(index(row, 0), index(row, 0));
}
void SipAddressesModel::handleLastEntryRemoved (ChatModel *chatModel) {
auto it = mSipAddresses.find(chatModel->getSipAddress());
if (it == mSipAddresses.end())
auto it = mPeerAddressToSipAddressEntry.find(chatModel->getPeerAddress());
if (it == mPeerAddressToSipAddressEntry.end())
return;
auto it2 = it->localAddressToConferenceEntry.find(chatModel->getLocalAddress());
if (it2 == it->localAddressToConferenceEntry.end())
return;
int row = mRefs.indexOf(&(*it));
@ -365,76 +381,96 @@ void SipAddressesModel::handleLastEntryRemoved (ChatModel *chatModel) {
).toMap();
// Update the timestamp with the new last chat message timestamp.
(*it)["timestamp"] = map["timestamp"];
it2->timestamp = map["timestamp"].toDateTime();
emit dataChanged(index(row, 0), index(row, 0));
}
void SipAddressesModel::handleMessagesCountReset (ChatModel *chatModel) {
const QString &sipAddress = chatModel->getSipAddress();
auto it = mSipAddresses.find(sipAddress);
if (it != mSipAddresses.end()) {
(*it)["unreadMessagesCount"] = 0;
void SipAddressesModel::handleMessageCountReset (ChatModel *chatModel) {
const QString &peerAddress = chatModel->getPeerAddress();
auto it = mPeerAddressToSipAddressEntry.find(peerAddress);
if (it == mPeerAddressToSipAddressEntry.end())
return;
int row = mRefs.indexOf(&(*it));
Q_ASSERT(row != -1);
emit dataChanged(index(row, 0), index(row, 0));
}
const QString &localAddress = chatModel->getLocalAddress();
auto it2 = it->localAddressToConferenceEntry.find(localAddress);
if (it2 == it->localAddressToConferenceEntry.end())
return;
updateObservers(sipAddress, 0);
it2->unreadMessageCount = 0;
int row = mRefs.indexOf(&(*it));
Q_ASSERT(row != -1);
emit dataChanged(index(row, 0), index(row, 0));
updateObservers(peerAddress, localAddress, 0);
}
void SipAddressesModel::handleMessageSent (const shared_ptr<linphone::ChatMessage> &message) {
addOrUpdateSipAddress(
Utils::coreStringToAppString(message->getToAddress()->asStringUriOnly()),
message
);
qInfo() << "Handle message sent.";
const QString peerAddress(Utils::coreStringToAppString(message->getChatRoom()->getPeerAddress()->asStringUriOnly()));
addOrUpdateSipAddress(peerAddress, message);
}
void SipAddressesModel::handlerIsComposingChanged (const shared_ptr<linphone::ChatRoom> &chatRoom) {
auto it = mSipAddresses.find(Utils::coreStringToAppString(chatRoom->getPeerAddress()->asStringUriOnly()));
if (it != mSipAddresses.end()) {
(*it)["isComposing"] = chatRoom->isRemoteComposing();
void SipAddressesModel::handleIsComposingChanged (const shared_ptr<linphone::ChatRoom> &chatRoom) {
auto it = mPeerAddressToSipAddressEntry.find(
Utils::coreStringToAppString(chatRoom->getPeerAddress()->asStringUriOnly())
);
if (it == mPeerAddressToSipAddressEntry.end())
return;
int row = mRefs.indexOf(&(*it));
Q_ASSERT(row != -1);
emit dataChanged(index(row, 0), index(row, 0));
}
auto it2 = it->localAddressToConferenceEntry.find(
Utils::coreStringToAppString(chatRoom->getLocalAddress()->asStringUriOnly())
);
if (it2 == it->localAddressToConferenceEntry.end())
return;
it2->isComposing = chatRoom->isRemoteComposing();
int row = mRefs.indexOf(&(*it));
Q_ASSERT(row != -1);
emit dataChanged(index(row, 0), index(row, 0));
}
// -----------------------------------------------------------------------------
void SipAddressesModel::addOrUpdateSipAddress (QVariantMap &map, ContactModel *contact) {
QString sipAddress = map["sipAddress"].toString();
void SipAddressesModel::addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, ContactModel *contact) {
const QString &sipAddress = sipAddressEntry.sipAddress;
if (contact)
map["contact"] = QVariant::fromValue(contact);
else if (map.remove("contact") == 0)
sipAddressEntry.contact = contact;
else if (!sipAddressEntry.contact)
qWarning() << QStringLiteral("`contact` field is empty on sip address: `%1`.").arg(sipAddress);
updateObservers(sipAddress, contact);
}
void SipAddressesModel::addOrUpdateSipAddress (QVariantMap &map, const shared_ptr<linphone::Call> &call) {
void SipAddressesModel::addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, const shared_ptr<linphone::Call> &call) {
const shared_ptr<linphone::CallLog> callLog = call->getCallLog();
map["timestamp"] = callLog->getStatus() == linphone::CallStatus::CallStatusSuccess
sipAddressEntry.localAddressToConferenceEntry[
Utils::coreStringToAppString(callLog->getLocalAddress()->asStringUriOnly())
].timestamp = callLog->getStatus() == linphone::Call::Status::Success
? QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000)
: QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000);
}
void SipAddressesModel::addOrUpdateSipAddress (QVariantMap &map, const shared_ptr<linphone::ChatMessage> &message) {
int count = message->getChatRoom()->getUnreadMessagesCount();
void SipAddressesModel::addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, const shared_ptr<linphone::ChatMessage> &message) {
shared_ptr<linphone::ChatRoom> chatRoom(message->getChatRoom());
int count = chatRoom->getUnreadMessagesCount();
map["timestamp"] = QDateTime::fromMSecsSinceEpoch(message->getTime() * 1000);
map["unreadMessagesCount"] = count;
QString localAddress(Utils::coreStringToAppString(chatRoom->getLocalAddress()->asStringUriOnly()));
qInfo() << QStringLiteral("Update (`%1`, `%2`) from chat message.").arg(sipAddressEntry.sipAddress, localAddress);
updateObservers(map["sipAddress"].toString(), count);
ConferenceEntry &conferenceEntry = sipAddressEntry.localAddressToConferenceEntry[localAddress];
conferenceEntry.timestamp = QDateTime::fromMSecsSinceEpoch(message->getTime() * 1000);
conferenceEntry.unreadMessageCount = count;
updateObservers(sipAddressEntry.sipAddress, localAddress, count);
}
template<typename T>
void SipAddressesModel::addOrUpdateSipAddress (const QString &sipAddress, T data) {
auto it = mSipAddresses.find(sipAddress);
if (it != mSipAddresses.end()) {
auto it = mPeerAddressToSipAddressEntry.find(sipAddress);
if (it != mPeerAddressToSipAddressEntry.end()) {
addOrUpdateSipAddress(*it, data);
int row = mRefs.indexOf(&(*it));
@ -444,18 +480,15 @@ void SipAddressesModel::addOrUpdateSipAddress (const QString &sipAddress, T data
return;
}
QVariantMap map;
map["sipAddress"] = sipAddress;
addOrUpdateSipAddress(map, data);
SipAddressEntry sipAddressEntry{ sipAddress, nullptr, Presence::Offline, {} };
addOrUpdateSipAddress(sipAddressEntry, data);
int row = mRefs.count();
beginInsertRows(QModelIndex(), row, row);
qInfo() << QStringLiteral("Add sip address: `%1`.").arg(sipAddress);
mSipAddresses[sipAddress] = map;
mRefs << &mSipAddresses[sipAddress];
mPeerAddressToSipAddressEntry[sipAddress] = move(sipAddressEntry);
mRefs << &mPeerAddressToSipAddressEntry[sipAddress];
endInsertRows();
}
@ -463,8 +496,8 @@ void SipAddressesModel::addOrUpdateSipAddress (const QString &sipAddress, T data
// -----------------------------------------------------------------------------
void SipAddressesModel::removeContactOfSipAddress (const QString &sipAddress) {
auto it = mSipAddresses.find(sipAddress);
if (it == mSipAddresses.end()) {
auto it = mPeerAddressToSipAddressEntry.find(sipAddress);
if (it == mPeerAddressToSipAddressEntry.end()) {
qWarning() << QStringLiteral("Unable to remove unavailable sip address: `%1`.").arg(sipAddress);
return;
}
@ -479,8 +512,8 @@ void SipAddressesModel::removeContactOfSipAddress (const QString &sipAddress) {
int row = mRefs.indexOf(&(*it));
Q_ASSERT(row != -1);
// History exists, signal changes.
if (it->contains("timestamp") || contactModel) {
// History or contact exists, signal changes.
if (!it->localAddressToConferenceEntry.empty() || contactModel) {
emit dataChanged(index(row, 0), index(row, 0));
return;
}
@ -492,53 +525,72 @@ void SipAddressesModel::removeContactOfSipAddress (const QString &sipAddress) {
// -----------------------------------------------------------------------------
void SipAddressesModel::initSipAddresses () {
QElapsedTimer timer;
timer.start();
initSipAddressesFromChat();
initSipAddressesFromCalls();
initRefs();
initSipAddressesFromContacts();
qInfo() << "Sip addresses model initialized in:" << timer.elapsed() << "ms.";
}
void SipAddressesModel::initSipAddressesFromChat () {
for (const auto &chatRoom : CoreManager::getInstance()->getCore()->getChatRooms()) {
list<shared_ptr<linphone::ChatMessage>> history = chatRoom->getHistory(1);
list<shared_ptr<linphone::ChatMessage>> history(chatRoom->getHistory(1));
if (history.empty())
continue;
QString sipAddress = Utils::coreStringToAppString(chatRoom->getPeerAddress()->asStringUriOnly());
QString peerAddress(Utils::coreStringToAppString(chatRoom->getPeerAddress()->asStringUriOnly()));
QString localAddress(Utils::coreStringToAppString(chatRoom->getLocalAddress()->asStringUriOnly()));
QVariantMap map;
map["sipAddress"] = sipAddress;
map["timestamp"] = QDateTime::fromMSecsSinceEpoch(history.back()->getTime() * 1000);
map["unreadMessagesCount"] = chatRoom->getUnreadMessagesCount();
mSipAddresses[sipAddress] = map;
getSipAddressEntry(peerAddress)->localAddressToConferenceEntry[localAddress] = {
chatRoom->getUnreadMessagesCount(),
false,
QDateTime::fromMSecsSinceEpoch(history.back()->getTime() * 1000)
};
}
}
void SipAddressesModel::initSipAddressesFromCalls () {
QSet<QString> addressDone;
using ConferenceId = QPair<QString, QString>;
QSet<ConferenceId> conferenceDone;
for (const auto &callLog : CoreManager::getInstance()->getCore()->getCallLogs()) {
const QString sipAddress = Utils::coreStringToAppString(callLog->getRemoteAddress()->asStringUriOnly());
const QString peerAddress(Utils::coreStringToAppString(callLog->getRemoteAddress()->asStringUriOnly()));
const QString localAddress(Utils::coreStringToAppString(callLog->getLocalAddress()->asStringUriOnly()));
if (addressDone.contains(sipAddress))
switch (callLog->getStatus()) {
case linphone::Call::Status::Aborted:
case linphone::Call::Status::EarlyAborted:
return; // Ignore aborted calls.
case linphone::Call::Status::AcceptedElsewhere:
case linphone::Call::Status::DeclinedElsewhere:
return; // Ignore accepted calls on other device.
case linphone::Call::Status::Success:
case linphone::Call::Status::Missed:
case linphone::Call::Status::Declined:
break;
}
ConferenceId conferenceId{ peerAddress, localAddress };
if (conferenceDone.contains(conferenceId))
continue; // Already used.
if (callLog->getStatus() == linphone::CallStatusAborted)
continue; // Ignore aborted calls.
addressDone << sipAddress;
QVariantMap map;
map["sipAddress"] = sipAddress;
conferenceDone << conferenceId;
// The duration can be wrong if status is not success.
map["timestamp"] = callLog->getStatus() == linphone::CallStatus::CallStatusSuccess
QDateTime timestamp(callLog->getStatus() == linphone::Call::Status::Success
? QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000)
: QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000);
: QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000));
auto it = mSipAddresses.find(sipAddress);
if (it == mSipAddresses.end() || map["timestamp"] > (*it)["timestamp"])
mSipAddresses[sipAddress] = map;
auto &localToConferenceEntry = getSipAddressEntry(peerAddress)->localAddressToConferenceEntry;
auto it = localToConferenceEntry.find(localAddress);
if (it == localToConferenceEntry.end())
localToConferenceEntry[localAddress] = { 0, false, move(timestamp) };
else if (it->timestamp.isNull() || timestamp > it->timestamp)
it->timestamp = move(timestamp);
}
}
@ -548,8 +600,8 @@ void SipAddressesModel::initSipAddressesFromContacts () {
}
void SipAddressesModel::initRefs () {
for (const auto &map : mSipAddresses)
mRefs << &map;
for (const auto &sipAddressEntry : mPeerAddressToSipAddressEntry)
mRefs << &sipAddressEntry;
}
// -----------------------------------------------------------------------------
@ -564,7 +616,10 @@ void SipAddressesModel::updateObservers (const QString &sipAddress, const Presen
observer->setPresenceStatus(presenceStatus);
}
void SipAddressesModel::updateObservers (const QString &sipAddress, int messagesCount) {
for (auto &observer : mObservers.values(sipAddress))
observer->setUnreadMessagesCount(messagesCount);
void SipAddressesModel::updateObservers (const QString &peerAddress, const QString &localAddress, int messageCount) {
for (auto &observer : mObservers.values(peerAddress))
if (observer->getLocalAddress() == localAddress) {
observer->setUnreadMessageCount(messageCount);
return;
}
}

View file

@ -24,6 +24,7 @@
#define SIP_ADDRESSES_MODEL_H_
#include <QAbstractListModel>
#include <QDateTime>
#include "SipAddressObserver.hpp"
@ -38,6 +39,19 @@ class SipAddressesModel : public QAbstractListModel {
Q_OBJECT;
public:
struct ConferenceEntry {
int unreadMessageCount;
bool isComposing;
QDateTime timestamp;
};
struct SipAddressEntry {
QString sipAddress;
ContactModel *contact;
Presence::PresenceStatus presenceStatus;
QHash<QString, ConferenceEntry> localAddressToConferenceEntry;
};
SipAddressesModel (QObject *parent = Q_NULLPTR);
int rowCount (const QModelIndex &index = QModelIndex()) const override;
@ -47,14 +61,14 @@ public:
Q_INVOKABLE QVariantMap find (const QString &sipAddress) const;
Q_INVOKABLE ContactModel *mapSipAddressToContact (const QString &sipAddress) const;
Q_INVOKABLE SipAddressObserver *getSipAddressObserver (const QString &sipAddress);
Q_INVOKABLE SipAddressObserver *getSipAddressObserver (const QString &peerAddress, const QString &localAddress);
// ---------------------------------------------------------------------------
// Sip addresses helpers.
// ---------------------------------------------------------------------------
Q_INVOKABLE QString getTransportFromSipAddress (const QString &sipAddress) const;
Q_INVOKABLE QString addTransportToSipAddress (const QString &sipAddress, const QString &transport) const;
Q_INVOKABLE static QString getTransportFromSipAddress (const QString &sipAddress);
Q_INVOKABLE static QString addTransportToSipAddress (const QString &sipAddress, const QString &transport);
Q_INVOKABLE static QString interpretSipAddress (const QString &sipAddress, bool checkUsername = true);
Q_INVOKABLE static QString interpretSipAddress (const QUrl &sipAddress);
@ -81,24 +95,24 @@ private:
void handleSipAddressRemoved (ContactModel *contact, const QString &sipAddress);
void handleMessageReceived (const std::shared_ptr<linphone::ChatMessage> &message);
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::CallState state);
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
void handlePresenceReceived (const QString &sipAddress, const std::shared_ptr<const linphone::PresenceModel> &presenceModel);
void handleAllEntriesRemoved (ChatModel *chatModel);
void handleLastEntryRemoved (ChatModel *chatModel);
void handleMessagesCountReset (ChatModel *chatModel);
void handleMessageCountReset (ChatModel *chatModel);
void handleMessageSent (const std::shared_ptr<linphone::ChatMessage> &message);
void handlerIsComposingChanged (const std::shared_ptr<linphone::ChatRoom> &chatRoom);
void handleIsComposingChanged (const std::shared_ptr<linphone::ChatRoom> &chatRoom);
// ---------------------------------------------------------------------------
// A sip address exists in this list if a contact is linked to it, or a call, or a message.
void addOrUpdateSipAddress (QVariantMap &map, ContactModel *contact);
void addOrUpdateSipAddress (QVariantMap &map, const std::shared_ptr<linphone::Call> &call);
void addOrUpdateSipAddress (QVariantMap &map, const std::shared_ptr<linphone::ChatMessage> &message);
void addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, ContactModel *contact);
void addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, const std::shared_ptr<linphone::Call> &call);
void addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, const std::shared_ptr<linphone::ChatMessage> &message);
template<class T>
void addOrUpdateSipAddress (const QString &sipAddress, T data);
@ -117,14 +131,26 @@ private:
void updateObservers (const QString &sipAddress, ContactModel *contact);
void updateObservers (const QString &sipAddress, const Presence::PresenceStatus &presenceStatus);
void updateObservers (const QString &sipAddress, int messagesCount);
void updateObservers (const QString &peerAddress, const QString &localAddress, int messageCount);
QHash<QString, QVariantMap> mSipAddresses;
QList<const QVariantMap *> mRefs;
// ---------------------------------------------------------------------------
SipAddressEntry *getSipAddressEntry (const QString &peerAddress) {
auto it = mPeerAddressToSipAddressEntry.find(peerAddress);
if (it == mPeerAddressToSipAddressEntry.end())
it = mPeerAddressToSipAddressEntry.insert(peerAddress, { peerAddress, nullptr, Presence::Offline, {} });
return &(*it);
}
QHash<QString, SipAddressEntry> mPeerAddressToSipAddressEntry;
QList<const SipAddressEntry *> mRefs;
QMultiHash<QString, SipAddressObserver *> mObservers;
std::shared_ptr<CoreHandlers> mCoreHandlers;
};
using LocalAddressToConferenceEntry = QHash<QString, SipAddressesModel::ConferenceEntry>;
Q_DECLARE_METATYPE(const LocalAddressToConferenceEntry *);
#endif // SIP_ADDRESSES_MODEL_H_

View file

@ -21,6 +21,7 @@
*/
#include "components/core/CoreManager.hpp"
#include "components/settings/AccountSettingsModel.hpp"
#include "components/sip-addresses/SipAddressesModel.hpp"
#include "TimelineModel.hpp"
@ -28,7 +29,15 @@
// =============================================================================
TimelineModel::TimelineModel (QObject *parent) : QSortFilterProxyModel(parent) {
setSourceModel(CoreManager::getInstance()->getSipAddressesModel());
CoreManager *coreManager = CoreManager::getInstance();
AccountSettingsModel *accountSettingsModel = coreManager->getAccountSettingsModel();
QObject::connect(accountSettingsModel, &AccountSettingsModel::accountSettingsUpdated, this, [this]() {
handleLocalAddressChanged(CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddressAsString());
});
mLocalAddress = accountSettingsModel->getUsedSipAddressAsString();
setSourceModel(coreManager->getSipAddressesModel());
sort(0);
}
@ -40,11 +49,40 @@ QHash<int, QByteArray> TimelineModel::roleNames () const {
// -----------------------------------------------------------------------------
static inline const QHash<QString, SipAddressesModel::ConferenceEntry> *getLocalToConferenceEntry (const QVariantMap &map) {
return map.value("__localToConferenceEntry").value<decltype(getLocalToConferenceEntry({}))>();
}
QVariant TimelineModel::data (const QModelIndex &index, int role) const {
QVariantMap map(QSortFilterProxyModel::data(index, role).toMap());
auto localToConferenceEntry = getLocalToConferenceEntry(map);
auto it = localToConferenceEntry->find(mLocalAddress);
if (it != localToConferenceEntry->end()) {
map["timestamp"] = it->timestamp;
map["isComposing"] = it->isComposing;
map["unreadMessageCount"] = it->unreadMessageCount;
}
return map;
}
bool TimelineModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const {
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
return index.data().toMap().contains("timestamp");
return getLocalToConferenceEntry(index.data().toMap())->contains(mLocalAddress);
}
bool TimelineModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
return sourceModel()->data(left).toMap()["timestamp"] > sourceModel()->data(right).toMap()["timestamp"];
const QDateTime &a(getLocalToConferenceEntry(sourceModel()->data(left).toMap())->find(mLocalAddress)->timestamp);
const QDateTime &b(getLocalToConferenceEntry(sourceModel()->data(right).toMap())->find(mLocalAddress)->timestamp);
return a > b;
}
// -----------------------------------------------------------------------------
void TimelineModel::handleLocalAddressChanged (const QString &localAddress) {
if (mLocalAddress != localAddress) {
mLocalAddress = localAddress;
invalidate();
}
}

View file

@ -30,14 +30,30 @@
class TimelineModel : public QSortFilterProxyModel {
Q_OBJECT;
Q_PROPERTY(QString localAddress READ getLocalAddress NOTIFY localAddressChanged);
public:
TimelineModel (QObject *parent = Q_NULLPTR);
QHash<int, QByteArray> roleNames () const override;
signals:
void localAddressChanged (const QString &localAddress);
protected:
QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
bool lessThan (const QModelIndex &left, const QModelIndex &right) const override;
QString getLocalAddress () const {
return mLocalAddress;
}
void handleLocalAddressChanged (const QString &localAddress);
private:
QString mLocalAddress;
};
#endif // TIMELINE_MODEL_H_

View file

@ -28,11 +28,11 @@
linphone::TransportType LinphoneUtils::stringToTransportType (const QString &transport) {
if (transport == QLatin1String("TCP"))
return linphone::TransportType::TransportTypeTcp;
return linphone::TransportType::Tcp;
if (transport == QLatin1String("UDP"))
return linphone::TransportType::TransportTypeUdp;
return linphone::TransportType::Udp;
if (transport == QLatin1String("TLS"))
return linphone::TransportType::TransportTypeTls;
return linphone::TransportType::Tls;
return linphone::TransportType::TransportTypeDtls;
return linphone::TransportType::Dtls;
}

@ -1 +1 @@
Subproject commit 48ac645caa629a65fb164882aeddab7eb13a56a9
Subproject commit 88ed003beb9a33d9d80bbac8c53287039e1e30b0

@ -1 +1 @@
Subproject commit 28b8552948d653bbe9b37f5f08473bb9e325829e
Subproject commit 41666379abcdd4f14fcf08732e21b2d7b81cf729

@ -1 +1 @@
Subproject commit af6d655f7bd493a139fdd9f8cb17806f61a35fd8
Subproject commit d70591056f0f6be78b713b966e98dc53c582fce5

@ -1 +1 @@
Subproject commit d2b4742a04da011adf05a4ea63d041f60e50195a
Subproject commit f80be22a1099b2a431c2796f529bb261064ec6b4

@ -1 +1 @@
Subproject commit a26a7854efb6b3c25f3bc3213851ef69cc999aa6
Subproject commit d1fc622b2cbe5fe9b55959b32af054c7ae75e1a1

1
submodules/externals/sqlite3 vendored Submodule

@ -0,0 +1 @@
Subproject commit 644f83a6e4764dc8bb00aa838799ace18b205247

View file

@ -1,70 +0,0 @@
############################################################################
# CMakeLists.txt
# Copyright (C) 2014 Belledonne Communications, Grenoble France
#
############################################################################
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
############################################################################
cmake_minimum_required(VERSION 2.6)
project(SQLITE3 C)
option(ENABLE_STATIC "Build static library (default is shared library)." OFF)
set(SOURCE_FILES sqlite3.c)
if(WIN32)
list(APPEND SOURCE_FILES sqlite3.def)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" OR CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
add_definitions(
-DSQLITE_OS_WINRT=1
-DSQLITE_WIN32_FILEMAPPING_API=1
-DSQLITE_OMIT_LOAD_EXTENSION
)
endif()
if(ENABLE_STATIC)
add_library(sqlite3 STATIC ${SOURCE_FILES})
else()
add_library(sqlite3 SHARED ${SOURCE_FILES})
if(MSVC)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/sqlite3.pdb
DESTINATION bin
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
endif()
endif()
endif()
install(TARGETS sqlite3
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
file(GLOB HEADER_FILES "*.h")
install(FILES ${HEADER_FILES}
DESTINATION include
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)

File diff suppressed because it is too large Load diff

View file

@ -1,28 +0,0 @@
LIBRARY sqlite3
EXPORTS
sqlite3_bind_blob
sqlite3_bind_int
sqlite3_bind_text
sqlite3_changes
sqlite3_close
sqlite3_column_blob
sqlite3_column_bytes
sqlite3_column_int
sqlite3_errmsg
sqlite3_exec
sqlite3_finalize
sqlite3_free
sqlite3_last_insert_rowid
sqlite3_mprintf
sqlite3_open
sqlite3_open_v2
sqlite3_open16
sqlite3_prepare
sqlite3_prepare_v2
sqlite3_profile
sqlite3_snprintf
sqlite3_step
sqlite3_vfs_find
sqlite3_vfs_register
sqlite3_vfs_unregister

File diff suppressed because it is too large Load diff

@ -1 +1 @@
Subproject commit dacbddbd19a5b81df66c97e4c99b71dc99120228
Subproject commit a0ffff0225e8984dc793bbf3b652186fc5995933

@ -1 +1 @@
Subproject commit 9add24c2041e1bcf7b51ae580575ef56aa408f3e
Subproject commit 0a872c0121f660d1d7054a53cc298e85df257d48

@ -1 +1 @@
Subproject commit ad3c3fc7ee789baaf9075a6ecdb9de8e585a088d
Subproject commit 17be28e9d0b8e50b89ff9fba75990a51f03f111e

View file

@ -57,7 +57,7 @@ Item {
var count = 0
exclusiveButtons.clicked.connect(function (_button) {
button = _button;
button = _button
count += 1
})

View file

@ -55,7 +55,7 @@ function getSelectedEntryText () {
return ''
}
function getEntryIcon (item) {
function getItemIcon (item) {
var iconRole = comboBox.iconRole
if (iconRole == null || iconRole.length === 0) {
return ''

View file

@ -4,7 +4,6 @@ import QtQuick.Layouts 1.3
import Common 1.0
import Common.Styles 1.0
import Utils 1.0
import 'ComboBox.js' as Logic
@ -82,65 +81,13 @@ Controls.ComboBox {
// ---------------------------------------------------------------------------
delegate: Controls.ItemDelegate {
delegate: CommonItemDelegate {
id: item
readonly property var flattenedModel: comboBox.textRole.length &&
container: comboBox
flattenedModel: comboBox.textRole.length &&
(typeof modelData !== 'undefined' ? modelData : model)
hoverEnabled: true
itemIcon: Logic.getItemIcon(item)
width: comboBox.width
background: Rectangle {
color: item.hovered
? ComboBoxStyle.delegate.color.hovered
: ComboBoxStyle.delegate.color.normal
Rectangle {
anchors.left: parent.left
color: ComboBoxStyle.delegate.indicator.color
height: parent.height
width: ComboBoxStyle.delegate.indicator.width
visible: item.hovered
}
Rectangle {
anchors.bottom: parent.bottom
color: ComboBoxStyle.delegate.separator.color
height: ComboBoxStyle.delegate.separator.height
width: parent.width
visible: comboBox.count !== index + 1
}
}
contentItem: RowLayout {
spacing: ComboBoxStyle.delegate.contentItem.spacing
width: item.width
Icon {
icon: Logic.getEntryIcon(item)
iconSize: ComboBoxStyle.delegate.contentItem.iconSize
visible: icon.length > 0
}
Text {
Layout.fillWidth: true
color: ComboBoxStyle.delegate.contentItem.text.color
elide: Text.ElideRight
font {
bold: comboBox.currentIndex === index
pointSize: ComboBoxStyle.delegate.contentItem.text.pointSize
}
text: item.flattenedModel[textRole] || modelData
}
}
}
}

View file

@ -0,0 +1,79 @@
import QtQuick 2.7
import QtQuick.Controls 2.2 as Controls
import QtQuick.Layouts 1.3
import Common 1.0
import Common.Styles 1.0
// =============================================================================
Controls.ItemDelegate {
id: item
property var container
property var flattenedModel
property var itemIcon
default property alias _content: content.data
hoverEnabled: true
background: Rectangle {
color: item.hovered
? CommonItemDelegateStyle.color.hovered
: CommonItemDelegateStyle.color.normal
Rectangle {
anchors.left: parent.left
color: CommonItemDelegateStyle.indicator.color
height: parent.height
width: CommonItemDelegateStyle.indicator.width
visible: item.hovered
}
Rectangle {
anchors.bottom: parent.bottom
color: CommonItemDelegateStyle.separator.color
height: CommonItemDelegateStyle.separator.height
width: parent.width
visible: container.count !== index + 1
}
}
contentItem: RowLayout {
spacing: CommonItemDelegateStyle.contentItem.spacing
width: item.width
Icon {
icon: item.itemIcon
iconSize: CommonItemDelegateStyle.contentItem.iconSize
visible: icon.length > 0
}
Text {
Layout.fillWidth: true
color: CommonItemDelegateStyle.contentItem.text.color
elide: Text.ElideRight
font {
bold: container.currentIndex === index
pointSize: CommonItemDelegateStyle.contentItem.text.pointSize
}
text: item.flattenedModel[container.textRole] || modelData
}
Item {
id: content
Layout.preferredWidth: CommonItemDelegateStyle.contentItem.iconSize
Layout.preferredHeight: CommonItemDelegateStyle.contentItem.iconSize
}
}
}

View file

@ -0,0 +1,18 @@
// =============================================================================
// `ListItemSelector.qml` Logic.
// =============================================================================
.import 'qrc:/ui/scripts/Utils/utils.js' as Utils
// =============================================================================
function getItemIcon (item) {
var iconRole = view.iconRole
if (iconRole == null || iconRole.length === 0) {
return ''
}
return Utils.isFunction(iconRole)
? iconRole(item.flattenedModel)
: item.flattenedModel[iconRole]
}

View file

@ -0,0 +1,42 @@
import Common 1.0
import 'ListItemSelector.js' as Logic
// =============================================================================
ScrollableListViewField {
property alias currentIndex: view.currentIndex
property alias iconRole: view.iconRole
property alias model: view.model
property alias textRole: view.textRole
signal activated (int index)
radius: 0
ScrollableListView {
id: view
// -------------------------------------------------------------------------
property string textRole
property var iconRole
// -------------------------------------------------------------------------
anchors.fill: parent
currentIndex: -1
delegate: CommonItemDelegate {
id: item
container: view
flattenedModel: view.textRole.length &&
(typeof modelData !== 'undefined' ? modelData : model)
itemIcon: Logic.getItemIcon(item)
width: parent.width
onClicked: activated(index)
}
}
}

View file

@ -26,6 +26,10 @@ Item {
}
anchors.centerIn: parent
width: iconSize
height: iconSize
fillMode: Image.PreserveAspectFit
source: Utils.resolveImageUri(icon)
sourceSize.width: getIconSize()

View file

@ -34,31 +34,4 @@ QtObject {
property int pointSize: Units.dp * 10
}
}
property QtObject delegate: QtObject {
property QtObject color: QtObject {
property color hovered: Colors.o
property color normal: Colors.q
}
property QtObject contentItem: QtObject {
property int iconSize: 20
property int spacing: 5
property QtObject text: QtObject {
property color color: Colors.d
property int pointSize: Units.dp * 10
}
}
property QtObject indicator: QtObject {
property color color: Colors.i
property int width: 5
}
property QtObject separator: QtObject {
property color color: Colors.c
property int height: 1
}
}
}

Some files were not shown because too many files have changed in this diff Show more