Merge branch 'feature/dev_group_chat_integration' [Switch submodule branch]
3
.gitmodules
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`!)
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<source>iceStateInProgress</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Pågående</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>iceStateReflexiveConnection</source>
|
||||
|
|
|
|||
|
|
@ -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'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: <a href="%1">%1</a>
|
||||
</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>Ağ 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>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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> &) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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_
|
||||
|
|
@ -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_
|
||||
|
|
@ -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];
|
||||
}
|
||||
|
|
@ -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));
|
||||
|
|
@ -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_
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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 << ↦
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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
|
||||
2
submodules/externals/libvpx
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit d2b4742a04da011adf05a4ea63d041f60e50195a
|
||||
Subproject commit f80be22a1099b2a431c2796f529bb261064ec6b4
|
||||
2
submodules/externals/soci
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit a26a7854efb6b3c25f3bc3213851ef69cc999aa6
|
||||
Subproject commit d1fc622b2cbe5fe9b55959b32af054c7ae75e1a1
|
||||
1
submodules/externals/sqlite3
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 644f83a6e4764dc8bb00aa838799ace18b205247
|
||||
70
submodules/externals/sqlite3/CMakeLists.txt
vendored
|
|
@ -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
|
||||
)
|
||||
140456
submodules/externals/sqlite3/sqlite3.c
vendored
28
submodules/externals/sqlite3/sqlite3.def
vendored
|
|
@ -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
|
||||
7245
submodules/externals/sqlite3/sqlite3.h
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit dacbddbd19a5b81df66c97e4c99b71dc99120228
|
||||
Subproject commit a0ffff0225e8984dc793bbf3b652186fc5995933
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 9add24c2041e1bcf7b51ae580575ef56aa408f3e
|
||||
Subproject commit 0a872c0121f660d1d7054a53cc298e85df257d48
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit ad3c3fc7ee789baaf9075a6ecdb9de8e585a088d
|
||||
Subproject commit 17be28e9d0b8e50b89ff9fba75990a51f03f111e
|
||||
|
|
@ -57,7 +57,7 @@ Item {
|
|||
var count = 0
|
||||
|
||||
exclusiveButtons.clicked.connect(function (_button) {
|
||||
button = _button;
|
||||
button = _button
|
||||
count += 1
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ function getSelectedEntryText () {
|
|||
return ''
|
||||
}
|
||||
|
||||
function getEntryIcon (item) {
|
||||
function getItemIcon (item) {
|
||||
var iconRole = comboBox.iconRole
|
||||
if (iconRole == null || iconRole.length === 0) {
|
||||
return ''
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
79
ui/modules/Common/Form/CommonItemDelegate.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
18
ui/modules/Common/Form/ListItemSelector.js
Normal 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]
|
||||
}
|
||||
42
ui/modules/Common/Form/ListItemSelector.qml
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,10 @@ Item {
|
|||
}
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
width: iconSize
|
||||
height: iconSize
|
||||
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: Utils.resolveImageUri(icon)
|
||||
sourceSize.width: getIconSize()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||