Compare commits
11 Commits
work/calls
...
work/carl/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbd81b4eda | ||
|
|
c51a1f4851 | ||
|
|
a27f4765e4 | ||
|
|
402f99923c | ||
|
|
2afda78912 | ||
|
|
25f9c7e125 | ||
|
|
05082cb2bb | ||
|
|
59495a1452 | ||
|
|
d10460c45b | ||
|
|
b968c85de2 | ||
|
|
13efc08b07 |
@@ -145,14 +145,6 @@ if(ANDROID)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/android/version.gradle.in ${CMAKE_BINARY_DIR}/version.gradle)
|
||||
endif()
|
||||
|
||||
include(FindPkgConfig)
|
||||
pkg_check_modules(GSTREAMER IMPORTED_TARGET gstreamer-sdp-1.0>1.18 gstreamer-webrtc-1.0>=1.18)
|
||||
if (TARGET PkgConfig::GSTREAMER)
|
||||
add_feature_info(voip ON "GStreamer found. Call support is enabled.")
|
||||
else()
|
||||
add_feature_info(voip OFF "GStreamer not found. Call support is disabled.")
|
||||
endif()
|
||||
|
||||
ki18n_install(po)
|
||||
|
||||
install(FILES org.kde.neochat.desktop DESTINATION ${KDE_INSTALL_APPDIR})
|
||||
|
||||
@@ -6,8 +6,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"PO-Revision-Date: 2023-06-08 10:55+0400\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-15 09:40+0400\n"
|
||||
"Last-Translator: Zayed Al-Saidi <zayed.alsaidi@gmail.com>\n"
|
||||
"Language-Team: ar\n"
|
||||
"Language: ar\n"
|
||||
@@ -84,10 +84,9 @@ msgid "Room creation failed: %1"
|
||||
msgstr "فشل إنشاء غرفة: %1"
|
||||
|
||||
#: src/controller.cpp:552
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Room creation failed: %1"
|
||||
#, kde-format
|
||||
msgid "Space creation failed: %1"
|
||||
msgstr "فشل إنشاء غرفة: %1"
|
||||
msgstr "فشل إنشاء فضاء: %1"
|
||||
|
||||
#: src/controller.cpp:566
|
||||
#, kde-format
|
||||
@@ -123,90 +122,90 @@ msgstr "المقصد"
|
||||
msgid "Network Error"
|
||||
msgstr "خطأ شبكيّ"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "نيوتشات"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "عميل ماتركس"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020بلاك هات، 2020-2023 مجتمع كِيدِي"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "كارل شوان"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "المصين"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "توبياس فلة"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "جيمس غراهام"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "قبعة سوداء"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "المؤلف الأصلي لـSpectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "أليكسي روساكوف"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "مصين Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "زايد السعيدي"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "zayed.alsaidi@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "مكتبة Qt5 لكتابة عملاء عابرة للأنظمة لماتركس"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (بني على %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "عميل لميفاق الاتصال ماتركس"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "يدعم ماتركس: مخطط الروابط"
|
||||
@@ -638,18 +637,16 @@ msgid "Custom"
|
||||
msgstr "مخصّص"
|
||||
|
||||
#: src/models/imagepacksmodel.cpp:90
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Own Stickers"
|
||||
#, kde-format
|
||||
msgctxt "As in 'The user's own Stickers'"
|
||||
msgid "Own Stickers"
|
||||
msgstr "ملصقاتك"
|
||||
|
||||
#: src/models/imagepacksmodel.cpp:90
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Emojis"
|
||||
#, kde-format
|
||||
msgctxt "As in 'The user's own emojis"
|
||||
msgid "Own Emojis"
|
||||
msgstr "الصورة التعبيرية"
|
||||
msgstr "صورك التعبيرية"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:477 src/models/messageeventmodel.cpp:486
|
||||
#, kde-format
|
||||
@@ -661,17 +658,17 @@ msgstr "<i>[هذه الرسالة محذوفة]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[هذه الرسالة محذوفة: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[أفعال محظورة]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[أفعال محظورة: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
@@ -682,7 +679,7 @@ msgstr[3] "%1 مستخدمين: "
|
||||
msgstr[4] " %1 مستخدماً: "
|
||||
msgstr[5] "%1 مستخدم: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1317,10 +1314,9 @@ msgid "Available Room Versions"
|
||||
msgstr "إصدارات الغرفة المتوفرة"
|
||||
|
||||
#: src/qml/Component/Emoji/EmojiGrid.qml:83
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Stickers"
|
||||
#, kde-format
|
||||
msgid "No stickers"
|
||||
msgstr "الملصقات"
|
||||
msgstr "لا يوجد ملصقات"
|
||||
|
||||
#: src/qml/Component/Emoji/EmojiGrid.qml:83
|
||||
#, kde-format
|
||||
@@ -1602,22 +1598,22 @@ msgstr "اختر ملف محلي"
|
||||
msgid "Clipboard image"
|
||||
msgstr "صورة الحافظة"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "اقفز إلى أول رسالة غير المقروءة"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "اقفز إلى أحدث رسالة"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "اسحب عناصر هنا لتشاركهم"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
@@ -1684,38 +1680,30 @@ msgstr "حسنًا"
|
||||
|
||||
#: src/qml/Dialog/CreateSpaceDialog.qml:15
|
||||
#: src/qml/Page/RoomList/ExploreComponent.qml:40
|
||||
#, fuzzy, kde-format
|
||||
#| msgctxt "'Space' is a matrix space"
|
||||
#| msgid "Leave Space"
|
||||
#, kde-format
|
||||
msgid "Create a Space"
|
||||
msgstr "اترك الفضاء"
|
||||
msgstr "أنشئ فضاء"
|
||||
|
||||
#: src/qml/Dialog/CreateSpaceDialog.qml:23
|
||||
#, fuzzy, kde-format
|
||||
#| msgctxt "'Space' is a matrix space"
|
||||
#| msgid "Leave Space"
|
||||
#, kde-format
|
||||
msgctxt "@title"
|
||||
msgid "Create a Space"
|
||||
msgstr "اترك الفضاء"
|
||||
msgstr "أنشئ فضاء"
|
||||
|
||||
#: src/qml/Dialog/CreateSpaceDialog.qml:27
|
||||
#, fuzzy, kde-format
|
||||
#| msgctxt "@option:check"
|
||||
#| msgid "Space members"
|
||||
#, kde-format
|
||||
msgid "Space name"
|
||||
msgstr "أعضاء الفضاء"
|
||||
msgstr "اسم الفضاء"
|
||||
|
||||
#: src/qml/Dialog/CreateSpaceDialog.qml:31
|
||||
#, kde-format
|
||||
msgid "Space topic (optional)"
|
||||
msgstr ""
|
||||
msgstr "موضوع الفضاء (اختياري)"
|
||||
|
||||
#: src/qml/Dialog/CreateSpaceDialog.qml:34
|
||||
#, fuzzy, kde-format
|
||||
#| msgctxt "'Space' is a matrix space"
|
||||
#| msgid "Leave Space"
|
||||
#, kde-format
|
||||
msgid "Create space"
|
||||
msgstr "اترك الفضاء"
|
||||
msgstr "أنشئ فضاء"
|
||||
|
||||
#: src/qml/Dialog/KeyVerification/EmojiSas.qml:23
|
||||
#, kde-format
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2022-07-22 12:13+0400\n"
|
||||
"Last-Translator: Kheyyam <xxmn77@gmail.com>\n"
|
||||
"Language-Team: Azerbaijani <kde-i18n-doc@kde.org>\n"
|
||||
@@ -130,92 +130,92 @@ msgstr "Dəvət göndərmək"
|
||||
msgid "Network Error"
|
||||
msgstr "Şəbəkə xətası"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix müştərisi"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2022 KDE Cəmiyyəti"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Qarapapaq"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Xəyyam Qocayev"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "xxmn77@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
"Matrix üçün platformalararası müştərilər yazmaq üçün bir Qt5 kitabxanası"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Matrix kommunikasiya protokolu üçün müştəri"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Supports appstream: url scheme"
|
||||
msgid "Supports matrix: url scheme"
|
||||
@@ -741,24 +741,24 @@ msgstr "<i>[Bu ismarıc silindi]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Bu ismarıc silindi: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[DÜZƏLİŞ_EDİLDİ]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[DÜZƏLİŞ_EDİLDİ: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, fuzzy, kde-format
|
||||
#| msgctxt "[action 1], [action 2 and action 3]"
|
||||
#| msgid ", "
|
||||
@@ -1713,22 +1713,22 @@ msgstr "Yerli faylı seçin"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Mübadilə yaddaşındakı şəkil"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Birinci oxunmammış ismarıca keçin"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Sonuncu ismarıca keçin"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Elementi paylaşmaq üçün buraya atın"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -9,7 +9,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-09 10:13+0200\n"
|
||||
"Last-Translator: Josep M. Ferrer <txemaq@gmail.com>\n"
|
||||
"Language-Team: Catalan <kde-i18n-ca@kde.org>\n"
|
||||
@@ -126,91 +126,91 @@ msgstr "Destinació"
|
||||
msgid "Network Error"
|
||||
msgstr "Error de la xarxa"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Client de Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2023 la comunitat KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Mantenidor"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "Nate Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Autor original de l'Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Mantenidor del Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Josep M. Ferrer"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "txemaq@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
"Una biblioteca Qt5 per a escriure clients multiplataforma per al Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (construïda amb %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Client per al protocol de comunicacions Matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Implementa l'esquema d'URL «matrix:»"
|
||||
@@ -656,24 +656,24 @@ msgstr "<i>[Aquest missatge s'ha suprimit]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Aquest missatge s'ha suprimit: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[REDACTAT]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[REDACTAT: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "%1 usuari: "
|
||||
msgstr[1] "%1 usuaris: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1586,22 +1586,22 @@ msgstr "Trieu un fitxer local"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Imatge del porta-retalls"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Ves al primer missatge sense llegir"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Ves al darrer missatge"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Arrossegueu aquí els elements per a compartir"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -9,7 +9,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-09 10:13+0200\n"
|
||||
"Last-Translator: Josep M. Ferrer <txemaq@gmail.com>\n"
|
||||
"Language-Team: Catalan <kde-i18n-ca@kde.org>\n"
|
||||
@@ -127,90 +127,90 @@ msgstr "Destinació"
|
||||
msgid "Network Error"
|
||||
msgstr "S'ha produït un error de la xarxa"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Client de Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2023 la comunitat KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Mantenidor"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "Nate Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Autor original d'Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Mantenidor de Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Josep M. Ferrer"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "txemaq@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Una biblioteca Qt5 per a escriure clients multiplataforma per a Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (construïda amb %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Client per al protocol de comunicacions Matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Implementa l'esquema d'URL «matrix:»"
|
||||
@@ -656,24 +656,24 @@ msgstr "<i>[Este missatge s'ha suprimit]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Este missatge s'ha suprimit: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[REDACTAT]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[REDACTAT: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "%1 usuari: "
|
||||
msgstr[1] "%1 usuaris: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1585,22 +1585,22 @@ msgstr "Seleccioneu un fitxer local"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Imatge del porta-retalls"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Ves al primer missatge sense llegir"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Ves al últim missatge"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Arrossegueu ací els elements per a compartir"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -6,8 +6,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"PO-Revision-Date: 2023-06-05 13:18+0200\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-12 16:22+0200\n"
|
||||
"Last-Translator: Vit Pelcak <vit@pelcak.org>\n"
|
||||
"Language-Team: Czech <kde-i18n-doc@kde.org>\n"
|
||||
"Language: cs\n"
|
||||
@@ -15,7 +15,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
"X-Generator: Lokalize 23.04.1\n"
|
||||
"X-Generator: Lokalize 23.04.2\n"
|
||||
|
||||
#: src/controller.cpp:262
|
||||
#, kde-format
|
||||
@@ -85,7 +85,7 @@ msgstr "Vytvoření místnosti selhalo: %1"
|
||||
#: src/controller.cpp:552
|
||||
#, kde-format
|
||||
msgid "Space creation failed: %1"
|
||||
msgstr ""
|
||||
msgstr "Vytvoření místnosti selhalo: %1"
|
||||
|
||||
#: src/controller.cpp:566
|
||||
#, kde-format
|
||||
@@ -121,90 +121,90 @@ msgstr "Cíl"
|
||||
msgid "Network Error"
|
||||
msgstr "Chyba sítě"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Klient protokolu Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2023 Komunita KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Správce"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Vít Pelčák"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "vit@pelcak.org"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (sestaveno oproti %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr ""
|
||||
@@ -633,13 +633,13 @@ msgstr "Vlastní"
|
||||
#, kde-format
|
||||
msgctxt "As in 'The user's own Stickers'"
|
||||
msgid "Own Stickers"
|
||||
msgstr ""
|
||||
msgstr "Vlastní nálepky"
|
||||
|
||||
#: src/models/imagepacksmodel.cpp:90
|
||||
#, kde-format
|
||||
msgctxt "As in 'The user's own emojis"
|
||||
msgid "Own Emojis"
|
||||
msgstr ""
|
||||
msgstr "Vlastní emotikony"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:477 src/models/messageeventmodel.cpp:486
|
||||
#, kde-format
|
||||
@@ -651,17 +651,17 @@ msgstr ""
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
@@ -669,7 +669,7 @@ msgstr[0] "%1 uživatel:"
|
||||
msgstr[1] "%1 uživatelé:"
|
||||
msgstr[2] "%1 uživatelů:"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1299,7 +1299,7 @@ msgstr "Dostupné verze místnosti"
|
||||
#: src/qml/Component/Emoji/EmojiGrid.qml:83
|
||||
#, kde-format
|
||||
msgid "No stickers"
|
||||
msgstr ""
|
||||
msgstr "Žádné nálepky"
|
||||
|
||||
#: src/qml/Component/Emoji/EmojiGrid.qml:83
|
||||
#, kde-format
|
||||
@@ -1578,22 +1578,22 @@ msgstr ""
|
||||
msgid "Clipboard image"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Přejít na první nepřečtenou zprávu"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
@@ -1659,28 +1659,28 @@ msgstr "OK"
|
||||
#: src/qml/Page/RoomList/ExploreComponent.qml:40
|
||||
#, kde-format
|
||||
msgid "Create a Space"
|
||||
msgstr ""
|
||||
msgstr "Vytvořit místnost"
|
||||
|
||||
#: src/qml/Dialog/CreateSpaceDialog.qml:23
|
||||
#, kde-format
|
||||
msgctxt "@title"
|
||||
msgid "Create a Space"
|
||||
msgstr ""
|
||||
msgstr "Vytvořit místnost"
|
||||
|
||||
#: src/qml/Dialog/CreateSpaceDialog.qml:27
|
||||
#, kde-format
|
||||
msgid "Space name"
|
||||
msgstr ""
|
||||
msgstr "Název místnosti"
|
||||
|
||||
#: src/qml/Dialog/CreateSpaceDialog.qml:31
|
||||
#, kde-format
|
||||
msgid "Space topic (optional)"
|
||||
msgstr ""
|
||||
msgstr "Téma místnosti (volitelné)"
|
||||
|
||||
#: src/qml/Dialog/CreateSpaceDialog.qml:34
|
||||
#, kde-format
|
||||
msgid "Create space"
|
||||
msgstr ""
|
||||
msgstr "Vytvořit místnost"
|
||||
|
||||
#: src/qml/Dialog/KeyVerification/EmojiSas.qml:23
|
||||
#, kde-format
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2020-12-13 17:28+0100\n"
|
||||
"Last-Translator: Martin Schlander <mschlander@opensuse.org>\n"
|
||||
"Language-Team: Danish <kde-i18n-doc@kde.org>\n"
|
||||
@@ -127,91 +127,91 @@ msgstr ""
|
||||
msgid "Network Error"
|
||||
msgstr "Netværksfejl"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Chat"
|
||||
msgid "NeoChat"
|
||||
msgstr "Chat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Martin Schlander"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "mschlander@opensuse.org"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr ""
|
||||
@@ -660,24 +660,24 @@ msgstr ""
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1607,22 +1607,22 @@ msgstr ""
|
||||
msgid "Clipboard image"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Gå til første ulæste besked"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -9,7 +9,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-05 13:08+0200\n"
|
||||
"Last-Translator: Frederik Schwarzer <schwarzer@kde.org>\n"
|
||||
"Language-Team: German <kde-i18n-de@kde.org>\n"
|
||||
@@ -127,92 +127,92 @@ msgstr "Ziel"
|
||||
msgid "Network Error"
|
||||
msgstr "Netzwerkfehler"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix-Programm"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "Copyright © 2018-2020 Black Hat, 2020-2023 KDE-Gemeinschaft"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Betreuer"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Ursprünglicher Autor von Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Betreuer von Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Deutsches KDE-Übersetzerteam, Alois Spitzbart"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "kde-i18n-de@kde.org, spitz234@hotmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
"Eine Qt5-Bibliothek zum Schreiben von plattformübergreifenden Programmen für "
|
||||
"Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (für %2 kompiliert)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Programm für das Matrix-Protokoll"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Unterstützt das Adressschema matrix:"
|
||||
@@ -666,24 +666,24 @@ msgstr "<i>[Diese Nachricht wurde gelöscht]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Diese Nachricht wurde gelöscht: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[GELÖSCHT]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[GELÖSCHT: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "1 Benutzer: "
|
||||
msgstr[1] "%1 Benutzer: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1595,22 +1595,22 @@ msgstr "Lokale Datei auswählen"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Bild aus Zwischenablage"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Zur ersten ungelesenen Nachricht springen"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Zur neuesten Nachricht springen"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Einträge hier einfügen um sie zu teilen"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-01-06 16:47+0200\n"
|
||||
"Last-Translator: Stelios <sstavra@gmail.com>\n"
|
||||
"Language-Team: Greek <kde-i18n-el@kde.org>\n"
|
||||
@@ -125,93 +125,93 @@ msgstr "Προορισμός"
|
||||
msgid "Network Error"
|
||||
msgstr "Σφάλμα δικτύου"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Πελάτης του Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Συντηρητής"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Αρχικός συγγραφέας του Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Συντηρητής του Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Stelios"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "sstavra@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
"Μια βιβλιοθήκη Qt5 για τη συγγραφή πελατών ανεξάρτητων από πλατφόρμες για το "
|
||||
"Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (κατασκευάστηκε με τη %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Πελάτης για το πρωτόκολλο επικοινωνίας Matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Υποστηρίζει το matrix: url σχήμα"
|
||||
@@ -670,24 +670,24 @@ msgstr "<i>[Αυτό το μήνυμα διαγράφηκε]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Αυτό το μήνυμα διαγράφηκε: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[ΔΙΑΓΡΑΜΜΕΝΟ]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[ΔΙΑΓΡΑΜΜΕΝΟ: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, fuzzy, kde-format
|
||||
#| msgctxt "[action 1], [action 2 and action 3]"
|
||||
#| msgid ", "
|
||||
@@ -1635,22 +1635,22 @@ msgstr "Επιλογή τοπικού αρχείου"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Εικόνα πρόχειρου"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Μετάβαση στο πρώτο μη αναγνωσμένο μήνυμα"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Μετάβαση στο τελευταίο μήνυμα"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Έλκυσε αντικείμενα εδώ για να τα μοιραστείς"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-05-21 15:04+0100\n"
|
||||
"Last-Translator: Steve Allewell <steve.allewell@gmail.com>\n"
|
||||
"Language-Team: British English\n"
|
||||
@@ -123,90 +123,90 @@ msgstr "Destination"
|
||||
msgid "Network Error"
|
||||
msgstr "Network Error"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix client"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Maintainer"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Original author of Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Maintainer of Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Steve Allewell"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "steve.allewell@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "A Qt5 library to write cross-platform clients for Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (built against %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Client for the matrix communication protocol"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Supports matrix: URL scheme"
|
||||
@@ -653,24 +653,24 @@ msgstr "<i>[This message was deleted]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[This message was deleted: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[REDACTED]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[REDACTED: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "1 user: "
|
||||
msgstr[1] "%1 users: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1581,22 +1581,22 @@ msgstr "Choose local file"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Clipboard image"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Jump to first unread message"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Jump to latest message"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Drag items here to share them"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-10 00:57+0200\n"
|
||||
"Last-Translator: Eloy Cuadra <ecuadra@eloihr.net>\n"
|
||||
"Language-Team: Spanish <kde-l10n-es@kde.org>\n"
|
||||
@@ -126,91 +126,91 @@ msgstr "Destino"
|
||||
msgid "Network Error"
|
||||
msgstr "Error de red"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Cliente para Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2023 La Comunidad KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Responsable"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Autor original de Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Responsable de Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Eloy Cuadra"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "ecuadra@eloihr.net"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
"Biblioteca Qt5 para la escritura de clientes multiplataforma para Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (compilado con %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Cliente para el protocolo de comunicaciones Matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Permite el esquema de URL «matrix:»"
|
||||
@@ -655,24 +655,24 @@ msgstr "<i>[Este mensaje ha sido borrado]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Este mensaje ha sido borrado: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[CORREGIDO]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[CORREGIDO: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "1 usuario: "
|
||||
msgstr[1] "%1 usuarios: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1582,22 +1582,22 @@ msgstr "Escoger archivo local"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Imagen del portapapeles"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Saltar al primer mensaje sin leer"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Saltar al último mensaje"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Arrastre elementos aquí para compartirlos"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -9,7 +9,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-04-22 21:58+0200\n"
|
||||
"Last-Translator: Iñigo Salvador Azurmendi <xalba@ni.eus>\n"
|
||||
"Language-Team: Basque <kde-i18n-eu@kde.org>\n"
|
||||
@@ -129,91 +129,91 @@ msgstr "Jomuga"
|
||||
msgid "Network Error"
|
||||
msgstr "Sareko errorea"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix bezeroa"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2022 KDE komunitatea"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Arduraduna"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "«Spectral»en Jatorrizko egilea"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "«Quotient»en arduraduna"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Iñigo Salvador Azurmendi"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "xalba@ni.eus"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Plataforma anitzeko Matrix bezeroak idazteko Qt5 liburutegi bat"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (%2 erabiliz eraikia)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Matrix, deszentralizatutako komunikazio protokolorako bezeroa"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "matrix onartzen du: URL eskema"
|
||||
@@ -661,24 +661,24 @@ msgstr "<i>[Mezu hau ezabatu egin da]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Mezu hau ezabatu egin da: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[ERREDAKZIO LANA DU]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[ERREDAKZIOAK LANA DU: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "Erabiltzaile 1:"
|
||||
msgstr[1] "%1 erabiltzaile:"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1597,22 +1597,22 @@ msgstr "Hautatu tokiko fitxategia"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Arbelako irudia"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Jauzi irakurri gabeko lehenengo mezura"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Jauzi azken mezura"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Arrastatu elementuak hona haiek partekatzeko"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-04-20 12:39+0300\n"
|
||||
"Last-Translator: Tommi Nieminen <translator@legisign.org>\n"
|
||||
"Language-Team: Finnish <kde-i18n-doc@kde.org>\n"
|
||||
@@ -123,91 +123,91 @@ msgstr "Kohde"
|
||||
msgid "Network Error"
|
||||
msgstr "Verkkovirhe"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix-asiakas"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018–2020 Black Hat, 2020–2022 KDE-yhteisö"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Ylläpitäjä"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Spectralin alkuperäinen tekijä"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Quotientin ylläpitäjä"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Tommi Nieminen"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "translator@legisign.org"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Qt5-kirjasto eri alustojen asiakkaiden Matrix-kirjoitukseen"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (koostettu kirjastolla %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Matrix-viestintäyhteyskäytäntöasiakas"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Tukee matrix:-verkko-osoitemallia"
|
||||
@@ -654,24 +654,24 @@ msgstr "<i>[Tämä viesti on poistettu]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Tämä viesti on poistettu: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[MUOKATTU]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[MUOKATTU: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "1 käyttäjä: "
|
||||
msgstr[1] "%1 käyttäjää: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1590,22 +1590,22 @@ msgstr "Valitse paikallinen tiedosto"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Leikepöydän kuva"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Hyppää ensimmäiseen lukemattomaan viestiin"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Hyppää viimeisimpään viestiin"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Jaa kohteita vetämällä ne tähän"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -4,7 +4,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-07 09:43+0200\n"
|
||||
"Last-Translator: Xavier BESNARD <xavier.besnard@neuf.fr>\n"
|
||||
"Language-Team: fr\n"
|
||||
@@ -123,91 +123,91 @@ msgstr "Destination"
|
||||
msgid "Network Error"
|
||||
msgstr "Erreur du réseau"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Client « Matrix »"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat 2020-2023 Communauté de KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Mainteneur"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Auteur initial de Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Mainteneur de Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Xavier Besnard"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "xavier.besnard@neuf.fr"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
"Une bibliothèque Qt5 pour écrire des clients multi-plate-formes pour Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (compilé en regard de %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Un client pour le protocole de communications Matrix »"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Prend en charge le thème d'URL « matrix : »"
|
||||
@@ -659,24 +659,24 @@ msgstr "<i>[Ce message a été supprimé]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Ce message a été supprimé : %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[RÉDIGÉ]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[RÉDIGÉ : %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] " utilisateur %1 :"
|
||||
msgstr[1] " %1 utilisateurs :"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1587,22 +1587,22 @@ msgstr "Sélectionner un fichier local"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Image du presse-papier"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Aller au premier message non lu."
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Aller au message le plus ancien."
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Faites glisser les éléments ici pour les partager"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-05-09 22:36+0200\n"
|
||||
"Last-Translator: K. Áron <aronkvh@gmail.com>\n"
|
||||
"Language-Team: Hungarian <kde-l10n-hu@kde.org>\n"
|
||||
@@ -129,91 +129,91 @@ msgstr "Célhely"
|
||||
msgid "Network Error"
|
||||
msgstr "Hálózati hiba"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix kliens"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© Black Hat, 2018-2020, A KDE közösség, 2020-2022"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Karbantartó"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "A Spectral eredeti készítője"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "A Quotient karbantartója"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Kiszel Kristóf, Kovács Áron"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "kiszel.kristof@gmail.com, aronkvh@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Qt5 könyvtár cross-platform Matrix kliensek létrehozásához"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (fordítva ezzel: %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Kliens a matrix kommunikációs protokollhoz"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Támogatja a 'matrix:' url sémát"
|
||||
@@ -661,24 +661,24 @@ msgstr "<i>[Törölt üzenet]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Törölt üzenet: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[KITAKARVA]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[KITAKARVA: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "1 felhasználó: "
|
||||
msgstr[1] "%1 felhasználó: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1590,22 +1590,22 @@ msgstr "Helyi fájl kiválasztása"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Vágólap kép"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Ugrás az első olvasatlan üzenetre"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Ugrás a legújabb üzenetre"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Húzz ide elemeket a megosztásukhoz"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-11 22:43+0200\n"
|
||||
"Last-Translator: giovanni <g.sora@tiscali.it>\n"
|
||||
"Language-Team: Interlingua <kde-i18n-doc@kde.org>\n"
|
||||
@@ -122,92 +122,92 @@ msgstr "Destination"
|
||||
msgid "Network Error"
|
||||
msgstr "Error de rete"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "Neochat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Cliente de Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020 -2023 Communitate de KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Mantenitor"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Autor original de Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Mantenitor de Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Giovanni Sora"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "g.sora@tiscali.it"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
"Un bibliotheca de Qt5 per scriber clientes de cross-platform (platteformas "
|
||||
"cruciate) per Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (construite contra %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Cliente per le protocollo de cmmmunication de matrice"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Supporta matrix: url schema"
|
||||
@@ -652,24 +652,24 @@ msgstr "<i>[Iste message ha essite delite]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Iste message esseva delite: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[REAGITE]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[REAGITE: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "1 Usator: "
|
||||
msgstr[1] "%1 Usatores:"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1577,22 +1577,22 @@ msgstr "Selige file local"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Image de Area de transferentia"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Salta al prime message non legite"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Salta al ultime message"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Trahe elementos hic per compartir los"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-05-19 10:51+0700\n"
|
||||
"Last-Translator: Linerly <linerly@protonmail.com>\n"
|
||||
"Language-Team: Indonesian <kde-i18n-doc@kde.org>\n"
|
||||
@@ -125,90 +125,90 @@ msgstr "Tujuan"
|
||||
msgid "Network Error"
|
||||
msgstr "Kesalahan Jaringan"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Klien Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2023 Komunitas KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Pemelihara"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Penulis asli Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Pemelihara Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Linerly"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "linerly@protonmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Sebuah pustaka Qt5 untuk membuat klien lintas platform untuk Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (dibangun pada %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Klien untuk protokol komunikasi Matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Mendukung skema URL matrix:"
|
||||
@@ -658,24 +658,24 @@ msgstr "<i>[Pesan ini telah dihapus]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Pesan ini telah dihapus: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[DIHAPUS]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[DIHAPUS: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "%1 pengguna: "
|
||||
msgstr[1] "%1 pengguna"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1585,22 +1585,22 @@ msgstr "Pilih berkas lokal"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Gambar papan klip"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Pergi ke pesan pertama yang belum dibaca"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Pergi ke pesan terkini"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Seret item ke sini untuk membagikannya"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2022-10-28 19:18+0700\n"
|
||||
"Last-Translator: OIS <mistresssilvara@hotmail.com>\n"
|
||||
"Language-Team: kde-i18n-doc@kde.org\n"
|
||||
@@ -128,92 +128,92 @@ msgstr "Inviar un invitation"
|
||||
msgid "Network Error"
|
||||
msgstr "Errore de rete"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Un cliente de Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2022 li comunité de KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "OIS"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "mistresssilvara@hotmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
"Un biblioteca usante Qt5 por scrir transplatformal clientes por Matrix."
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Un cliente del protocol de communication Matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, fuzzy, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Ínsupportat schema de URL"
|
||||
@@ -701,24 +701,24 @@ msgstr "<i>[Ti missage esset removet]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Ti missage esset removet: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[CENSURAT]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[CENSURAT: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, fuzzy, kde-format
|
||||
#| msgctxt "[action 1], [action 2 and action 3]"
|
||||
#| msgid ", "
|
||||
@@ -1648,22 +1648,22 @@ msgstr "Selecter un local file"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Image in li Paperiere"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Ear al prim ínleet missage"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Ear al ultim missage"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-09 15:52+0200\n"
|
||||
"Last-Translator: Vincenzo Reale <smart2128vr@gmail.com>\n"
|
||||
"Language-Team: Italian <kde-i18n-it@kde.org>\n"
|
||||
@@ -122,90 +122,90 @@ msgstr "Destinazione"
|
||||
msgid "Network Error"
|
||||
msgstr "Errore di rete"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Client Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2023 La comunità KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Responsabile"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Autore originale di Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Responsabile di Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Vincenzo Reale"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "smart2128vr@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Una libreria Qt5 per scrivere client multipiattaforma per Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (compilato con %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Client per il protocollo di comunicazione matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Supporta schema URL matrix:"
|
||||
@@ -653,24 +653,24 @@ msgstr "<i>[Questo messaggio è stato eliminato]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Questo messaggio è stato eliminato: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[REDATTO]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[REDATTO: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "1 utente: "
|
||||
msgstr[1] "%1 utenti: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1580,22 +1580,22 @@ msgstr "Scegli file locale"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Immagine dagli appunti"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Passa al primo messaggio non letto"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Salta all'ultimo messaggio"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Trascina qui gli elementi per condividerli"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -2,7 +2,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2020-11-05 23:50-0800\n"
|
||||
"Last-Translator: Japanese KDE translation team <kde-jp@kde.org>\n"
|
||||
"Language-Team: Japanese <kde-jp@kde.org>\n"
|
||||
@@ -118,90 +118,90 @@ msgstr ""
|
||||
msgid "Network Error"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr ""
|
||||
@@ -644,23 +644,23 @@ msgstr ""
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1563,22 +1563,22 @@ msgstr ""
|
||||
msgid "Clipboard image"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-10 06:34+0200\n"
|
||||
"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
|
||||
"Language-Team: Georgian <kde-i18n-doc@kde.org>\n"
|
||||
@@ -122,91 +122,91 @@ msgstr "დანიშნულება"
|
||||
msgid "Network Error"
|
||||
msgstr "ქსელის შეცდომა"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix -ის კლიენტი"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr ""
|
||||
"© 2018-2020 Black Hat, 2020-2023 KDE -ის საზოგადოება, ყველა უფლება დაცულია"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "წამყვანი პროგრამისტი"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "ჯეიმს გრეჰემი"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Spectral- ის ორიგინალური ავტორი"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "ალექსეი რუსაკოვი"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "კოვოტიენტის პროგრამისტი"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Temuri Doghonadze"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "Temuri.doghonadze@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Qt5 ბიბლიოთეკა Matrix-ისთვის კლიენტების დასაწერად"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (აგებულია %2-ით)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "კლიენტი Matrix-ის კომუნიკაციის პროტოკოლისთვის"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Matrix-ის მხარდჭერა: ბმული სქემა"
|
||||
@@ -651,24 +651,24 @@ msgstr "<i>[ეს შეტყობინება წაშლილია]</
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[ეს შეტყობინება წაშლილია: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[ჩასწორებული]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[ჩასწორებულია: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "1 მომხმარებელი: "
|
||||
msgstr[1] "%1 მომხმარებელი: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1578,22 +1578,22 @@ msgstr "აირჩიეთ ლოკალური ფაილი"
|
||||
msgid "Clipboard image"
|
||||
msgstr "ბუფერის გამოსახულება"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "პირველ წაუკითხავ შეტყობინებაზე გადასვლა"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "უახლეს შეტყობინებებზე გადასვლა"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "გადმოათრიეთ საგნები აქ, მათ გასაზიარებლად"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2022-08-09 13:27+0200\n"
|
||||
"Last-Translator: Shinjo Park <kde@peremen.name>\n"
|
||||
"Language-Team: Korean <kde-kr@kde.org>\n"
|
||||
@@ -129,91 +129,91 @@ msgstr "초대 보내기"
|
||||
msgid "Network Error"
|
||||
msgstr "네트워크 오류"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix 클라이언트"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "박신조"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "kde@peremen.name"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "크로스 플랫폼 Matrix 클라이언트를 작성할 수 있는 Qt5 라이브러리"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Matrix 대화 프로토콜 클라이언트"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Supports appstream: url scheme"
|
||||
msgid "Supports matrix: url scheme"
|
||||
@@ -724,23 +724,23 @@ msgstr "<i>[이 메시지가 삭제됨]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[이 메시지가 삭제됨: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[검열됨]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[검열됨: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, fuzzy, kde-format
|
||||
#| msgctxt "[action 1], [action 2 and action 3]"
|
||||
#| msgid ", "
|
||||
@@ -1696,22 +1696,22 @@ msgstr "로컬 파일 선택"
|
||||
msgid "Clipboard image"
|
||||
msgstr "클립보드의 그림"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "첫 읽지 않은 메시지로 이동"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "최신 메시지로 이동"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "공유할 항목을 여기에 드래그"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-02-25 01:00+0000\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
@@ -122,90 +122,90 @@ msgstr ""
|
||||
msgid "Network Error"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr ""
|
||||
@@ -652,17 +652,17 @@ msgstr ""
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
@@ -671,7 +671,7 @@ msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
msgstr[3] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1580,22 +1580,22 @@ msgstr ""
|
||||
msgid "Clipboard image"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-09 11:04+0200\n"
|
||||
"Last-Translator: Freek de Kruijf <freekdekruijf@kde.nl>\n"
|
||||
"Language-Team: \n"
|
||||
@@ -122,90 +122,90 @@ msgstr "Bestemming"
|
||||
msgid "Network Error"
|
||||
msgstr "Netwerkfout"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "Neochat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix-client"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2023 KDE-gemeenschap"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Onderhouder"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Oorspronkelijke auteur van Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Onderhouder van Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Freek de Kruijf - 2020 t/m 2022"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "freekdekruijf@kde.nl"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Een Qt5 bibliotheek om cross-platform clients voor Matrix te schrijven"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (gebouwd tegen %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Client voor het matrix communicatieprotocol"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Ondersteunt matrix: url schema"
|
||||
@@ -650,24 +650,24 @@ msgstr "<i>[Dit bericht is verwijderd]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Dit bericht is verwijderd: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[GEREDIGEERD]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[GEREDIGEERD: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "1 gebruiker: "
|
||||
msgstr[1] "%1 gebruikers "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1577,22 +1577,22 @@ msgstr "Lokaal bestand kiezen"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Afbeelding in klembord"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Naar het eerste ongelezen bericht gaan"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Naar het laatste bericht gaan"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Items hierheen verslepen om ze te delen"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
156
po/nn/neochat.po
156
po/nn/neochat.po
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-09 00:48+0000\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"PO-Revision-Date: 2021-12-15 11:17+0100\n"
|
||||
"Last-Translator: Øystein Steffensen-Alværvik <oysteins.omsetting@protonmail."
|
||||
"com>\n"
|
||||
@@ -203,12 +203,12 @@ msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:323
|
||||
#: src/main.cpp:324
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Lynmeldingsklient for Matrix-protokollen"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:325
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr ""
|
||||
@@ -643,35 +643,35 @@ msgctxt "As in 'The user's own emojis"
|
||||
msgid "Own Emojis"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:469 src/models/messageeventmodel.cpp:478
|
||||
#: src/models/messageeventmodel.cpp:477 src/models/messageeventmodel.cpp:486
|
||||
#, kde-format
|
||||
msgid "<i>[This message was deleted]</i>"
|
||||
msgstr "<i>[Denne meldinga er sletta]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:470
|
||||
#: src/models/messageeventmodel.cpp:478
|
||||
#, kde-format
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Denne meldinga er sletta: %1]</i>"
|
||||
|
||||
# Eller «SENSURERT»?
|
||||
#: src/models/messageeventmodel.cpp:545
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[TREKT TILBAKE]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:545
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[TREKT TILBAKE: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:854
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:861
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -729,353 +729,353 @@ msgstr "Låg prioritet"
|
||||
msgid "Spaces"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/searchmodel.cpp:164
|
||||
#: src/models/searchmodel.cpp:261
|
||||
#, kde-format
|
||||
msgid "Today"
|
||||
msgstr "I dag"
|
||||
|
||||
#: src/models/searchmodel.cpp:167
|
||||
#: src/models/searchmodel.cpp:264
|
||||
#, kde-format
|
||||
msgid "Yesterday"
|
||||
msgstr "I går"
|
||||
|
||||
#: src/models/searchmodel.cpp:170
|
||||
#: src/models/searchmodel.cpp:267
|
||||
#, kde-format
|
||||
msgid "The day before yesterday"
|
||||
msgstr "I forgårs"
|
||||
|
||||
#: src/neochatroom.cpp:527
|
||||
#: src/neochatroom.cpp:530
|
||||
#, kde-format
|
||||
msgid "a file"
|
||||
msgstr "ei fil"
|
||||
|
||||
#: src/neochatroom.cpp:578
|
||||
#: src/neochatroom.cpp:581
|
||||
#, kde-format
|
||||
msgid "reinvited %1 to the room"
|
||||
msgstr "inviterte %1 på nytt til rommet"
|
||||
|
||||
#: src/neochatroom.cpp:580
|
||||
#: src/neochatroom.cpp:583
|
||||
#, kde-format
|
||||
msgctxt "Optional reason for an invitation"
|
||||
msgid ": %1"
|
||||
msgstr ": %1"
|
||||
|
||||
#: src/neochatroom.cpp:589 src/neochatroom.cpp:734
|
||||
#: src/neochatroom.cpp:592 src/neochatroom.cpp:737
|
||||
#, kde-format
|
||||
msgid "joined the room (repeated)"
|
||||
msgstr "kom inn i rommet (på nytt)"
|
||||
|
||||
#: src/neochatroom.cpp:591
|
||||
#: src/neochatroom.cpp:594
|
||||
#, kde-format
|
||||
msgid "invited %1 to the room"
|
||||
msgstr "inviterte %1 til rommet"
|
||||
|
||||
#: src/neochatroom.cpp:591 src/neochatroom.cpp:736
|
||||
#: src/neochatroom.cpp:594 src/neochatroom.cpp:739
|
||||
#, kde-format
|
||||
msgid "joined the room"
|
||||
msgstr "kom inn i rommet"
|
||||
|
||||
#: src/neochatroom.cpp:595
|
||||
#: src/neochatroom.cpp:598
|
||||
#, kde-format
|
||||
msgid ": %1"
|
||||
msgstr ": %1"
|
||||
|
||||
#: src/neochatroom.cpp:602 src/neochatroom.cpp:744
|
||||
#: src/neochatroom.cpp:605 src/neochatroom.cpp:747
|
||||
#, kde-format
|
||||
msgctxt "their refers to a singular user"
|
||||
msgid "cleared their display name"
|
||||
msgstr "fjerna visingsnamnet"
|
||||
|
||||
#: src/neochatroom.cpp:604
|
||||
#: src/neochatroom.cpp:607
|
||||
#, kde-format
|
||||
msgctxt "their refers to a singular user"
|
||||
msgid "changed their display name to %1"
|
||||
msgstr "endra visingsnamn til %1"
|
||||
|
||||
#: src/neochatroom.cpp:609 src/neochatroom.cpp:751
|
||||
#: src/neochatroom.cpp:612 src/neochatroom.cpp:754
|
||||
#, kde-format
|
||||
msgid " and "
|
||||
msgstr " og "
|
||||
|
||||
#: src/neochatroom.cpp:612 src/neochatroom.cpp:754
|
||||
#: src/neochatroom.cpp:615 src/neochatroom.cpp:757
|
||||
#, kde-format
|
||||
msgctxt "their refers to a singular user"
|
||||
msgid "cleared their avatar"
|
||||
msgstr "fjerna avataren"
|
||||
|
||||
#: src/neochatroom.cpp:618 src/neochatroom.cpp:760
|
||||
#: src/neochatroom.cpp:621 src/neochatroom.cpp:763
|
||||
#, kde-format
|
||||
msgid "set an avatar"
|
||||
msgstr "valde ein avatar"
|
||||
|
||||
#: src/neochatroom.cpp:620 src/neochatroom.cpp:762
|
||||
#: src/neochatroom.cpp:623 src/neochatroom.cpp:765
|
||||
#, kde-format
|
||||
msgctxt "their refers to a singular user"
|
||||
msgid "updated their avatar"
|
||||
msgstr "bytte avataren sin"
|
||||
|
||||
#: src/neochatroom.cpp:624 src/neochatroom.cpp:766
|
||||
#: src/neochatroom.cpp:627 src/neochatroom.cpp:769
|
||||
#, kde-format
|
||||
msgctxt "<user> changed nothing"
|
||||
msgid "changed nothing"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:630
|
||||
#: src/neochatroom.cpp:633
|
||||
#, kde-format
|
||||
msgid "withdrew %1's invitation"
|
||||
msgstr "trekte tilbake invitasjonen til %1"
|
||||
|
||||
#: src/neochatroom.cpp:630 src/neochatroom.cpp:772
|
||||
#: src/neochatroom.cpp:633 src/neochatroom.cpp:775
|
||||
#, kde-format
|
||||
msgid "rejected the invitation"
|
||||
msgstr "avviste invitasjonen"
|
||||
|
||||
#: src/neochatroom.cpp:634
|
||||
#: src/neochatroom.cpp:637
|
||||
#, kde-format
|
||||
msgid "unbanned %1"
|
||||
msgstr "oppheva utestenging av %1"
|
||||
|
||||
#: src/neochatroom.cpp:634 src/neochatroom.cpp:776
|
||||
#: src/neochatroom.cpp:637 src/neochatroom.cpp:779
|
||||
#, kde-format
|
||||
msgid "self-unbanned"
|
||||
msgstr "utestengde seg sjølv"
|
||||
|
||||
#: src/neochatroom.cpp:637
|
||||
#: src/neochatroom.cpp:640
|
||||
#, kde-format
|
||||
msgid "has put %1 out of the room: %2"
|
||||
msgstr "fjerna %1 frå rommet: %2"
|
||||
|
||||
#: src/neochatroom.cpp:638 src/neochatroom.cpp:778
|
||||
#: src/neochatroom.cpp:641 src/neochatroom.cpp:781
|
||||
#, kde-format
|
||||
msgid "left the room"
|
||||
msgstr "forlét rommet"
|
||||
|
||||
#: src/neochatroom.cpp:642
|
||||
#: src/neochatroom.cpp:645
|
||||
#, kde-format
|
||||
msgid "banned %1 from the room"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:644
|
||||
#: src/neochatroom.cpp:647
|
||||
#, kde-format
|
||||
msgid "banned %1 from the room: %2"
|
||||
msgstr "utestengde %1 frå rommet: %2"
|
||||
|
||||
#: src/neochatroom.cpp:647 src/neochatroom.cpp:783
|
||||
#: src/neochatroom.cpp:650 src/neochatroom.cpp:786
|
||||
#, kde-format
|
||||
msgid "self-banned from the room"
|
||||
msgstr "utestengde seg sjølv frå rommet"
|
||||
|
||||
#: src/neochatroom.cpp:651 src/neochatroom.cpp:786
|
||||
#: src/neochatroom.cpp:654 src/neochatroom.cpp:789
|
||||
#, kde-format
|
||||
msgid "requested an invite"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:651
|
||||
#: src/neochatroom.cpp:654
|
||||
#, kde-format
|
||||
msgid "requested an invite with reason: %1"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:655 src/neochatroom.cpp:790
|
||||
#: src/neochatroom.cpp:658 src/neochatroom.cpp:793
|
||||
#, kde-format
|
||||
msgid "made something unknown"
|
||||
msgstr "gjorde noko ukjend"
|
||||
|
||||
#: src/neochatroom.cpp:658 src/neochatroom.cpp:793
|
||||
#: src/neochatroom.cpp:661 src/neochatroom.cpp:796
|
||||
#, kde-format
|
||||
msgid "cleared the room main alias"
|
||||
msgstr "fjerna hovudaliaset til rommet"
|
||||
|
||||
#: src/neochatroom.cpp:658
|
||||
#: src/neochatroom.cpp:661
|
||||
#, kde-format
|
||||
msgid "set the room main alias to: %1"
|
||||
msgstr "bytte hovudalias for rommet til: %1"
|
||||
|
||||
#: src/neochatroom.cpp:661 src/neochatroom.cpp:796
|
||||
#: src/neochatroom.cpp:664 src/neochatroom.cpp:799
|
||||
#, kde-format
|
||||
msgid "cleared the room name"
|
||||
msgstr "fjerna romnamnet"
|
||||
|
||||
#: src/neochatroom.cpp:661
|
||||
#: src/neochatroom.cpp:664
|
||||
#, kde-format
|
||||
msgid "set the room name to: %1"
|
||||
msgstr "bytte romnamnet til: %1"
|
||||
|
||||
#: src/neochatroom.cpp:664 src/neochatroom.cpp:799
|
||||
#: src/neochatroom.cpp:667 src/neochatroom.cpp:802
|
||||
#, kde-format
|
||||
msgid "cleared the topic"
|
||||
msgstr "tømte emnefeltet"
|
||||
|
||||
#: src/neochatroom.cpp:665
|
||||
#: src/neochatroom.cpp:668
|
||||
#, kde-format
|
||||
msgid "set the topic to: %1"
|
||||
msgstr "bytte emnet til: %1"
|
||||
|
||||
#: src/neochatroom.cpp:671 src/neochatroom.cpp:802
|
||||
#: src/neochatroom.cpp:674 src/neochatroom.cpp:805
|
||||
#, kde-format
|
||||
msgid "changed the room avatar"
|
||||
msgstr "bytte ut romavataren"
|
||||
|
||||
#: src/neochatroom.cpp:674 src/neochatroom.cpp:805
|
||||
#: src/neochatroom.cpp:677 src/neochatroom.cpp:808
|
||||
#, kde-format
|
||||
msgid "activated End-to-End Encryption"
|
||||
msgstr "slå på ende-til-ende-kryptering"
|
||||
|
||||
#: src/neochatroom.cpp:677
|
||||
#: src/neochatroom.cpp:680
|
||||
#, kde-format
|
||||
msgid "upgraded the room to version %1"
|
||||
msgstr "oppgraderte rommet til versjon %1"
|
||||
|
||||
#: src/neochatroom.cpp:678
|
||||
#: src/neochatroom.cpp:681
|
||||
#, kde-format
|
||||
msgid "created the room, version %1"
|
||||
msgstr "oppretta rommet, versjon %1"
|
||||
|
||||
#: src/neochatroom.cpp:681 src/neochatroom.cpp:811
|
||||
#: src/neochatroom.cpp:684 src/neochatroom.cpp:814
|
||||
#, kde-format
|
||||
msgctxt "'power level' means permission level"
|
||||
msgid "changed the power levels for this room"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:685 src/neochatroom.cpp:815
|
||||
#: src/neochatroom.cpp:688 src/neochatroom.cpp:818
|
||||
#, kde-format
|
||||
msgid "changed the server access control lists for this room"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:689
|
||||
#: src/neochatroom.cpp:692
|
||||
#, kde-format
|
||||
msgctxt "[User] added <name> widget"
|
||||
msgid "added %1 widget"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:692
|
||||
#: src/neochatroom.cpp:695
|
||||
#, kde-format
|
||||
msgctxt "[User] removed <name> widget"
|
||||
msgid "removed %1 widget"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:694
|
||||
#: src/neochatroom.cpp:697
|
||||
#, kde-format
|
||||
msgctxt "[User] configured <name> widget"
|
||||
msgid "configured %1 widget"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:696
|
||||
#: src/neochatroom.cpp:699
|
||||
#, kde-format
|
||||
msgid "updated %1 state"
|
||||
msgstr "oppdaterte %1-tilstand"
|
||||
|
||||
#: src/neochatroom.cpp:697
|
||||
#: src/neochatroom.cpp:700
|
||||
#, kde-format
|
||||
msgid "updated %1 state for %2"
|
||||
msgstr "oppdaterte %1-tilstand for %2"
|
||||
|
||||
#: src/neochatroom.cpp:704 src/neochatroom.cpp:834
|
||||
#: src/neochatroom.cpp:707 src/neochatroom.cpp:837
|
||||
#, kde-format
|
||||
msgid "Unknown event"
|
||||
msgstr "Ukjend hending"
|
||||
|
||||
#: src/neochatroom.cpp:717
|
||||
#: src/neochatroom.cpp:720
|
||||
#, kde-format
|
||||
msgid "sent a message"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:721
|
||||
#: src/neochatroom.cpp:724
|
||||
#, kde-format
|
||||
msgid "sent a sticker"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:727
|
||||
#: src/neochatroom.cpp:730
|
||||
#, kde-format
|
||||
msgid "reinvited someone to the room"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:736
|
||||
#: src/neochatroom.cpp:739
|
||||
#, kde-format
|
||||
msgid "invited someone to the room"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:746
|
||||
#: src/neochatroom.cpp:749
|
||||
#, kde-format
|
||||
msgctxt "their refers to a singular user"
|
||||
msgid "changed their display name"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:772
|
||||
#: src/neochatroom.cpp:775
|
||||
#, kde-format
|
||||
msgid "withdrew a user's invitation"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:776
|
||||
#: src/neochatroom.cpp:779
|
||||
#, kde-format
|
||||
msgid "unbanned a user"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:778
|
||||
#: src/neochatroom.cpp:781
|
||||
#, kde-format
|
||||
msgid "put a user out of the room"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:781
|
||||
#: src/neochatroom.cpp:784
|
||||
#, kde-format
|
||||
msgid "banned a user from the room"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:793
|
||||
#: src/neochatroom.cpp:796
|
||||
#, kde-format
|
||||
msgid "set the room main alias"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:796
|
||||
#: src/neochatroom.cpp:799
|
||||
#, kde-format
|
||||
msgid "set the room name"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:799
|
||||
#: src/neochatroom.cpp:802
|
||||
#, kde-format
|
||||
msgid "set the topic"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:808
|
||||
#: src/neochatroom.cpp:811
|
||||
#, kde-format
|
||||
msgid "upgraded the room version"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:808
|
||||
#: src/neochatroom.cpp:811
|
||||
#, kde-format
|
||||
msgid "created the room"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:819
|
||||
#: src/neochatroom.cpp:822
|
||||
#, kde-format
|
||||
msgid "added a widget"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:822
|
||||
#: src/neochatroom.cpp:825
|
||||
#, kde-format
|
||||
msgid "removed a widget"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:824
|
||||
#: src/neochatroom.cpp:827
|
||||
#, kde-format
|
||||
msgid "configured a widget"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:826
|
||||
#: src/neochatroom.cpp:829
|
||||
#, kde-format
|
||||
msgid "updated the state"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:831
|
||||
#: src/neochatroom.cpp:834
|
||||
#, kde-format
|
||||
msgid "started a poll"
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:1730 src/neochatroom.cpp:1731
|
||||
#: src/neochatroom.cpp:1733 src/neochatroom.cpp:1734
|
||||
#, kde-format
|
||||
msgid "Report sent successfully."
|
||||
msgstr ""
|
||||
|
||||
#: src/neochatroom.cpp:2033 src/neochatroom.cpp:2041
|
||||
#: src/neochatroom.cpp:2036 src/neochatroom.cpp:2044
|
||||
#, kde-format
|
||||
msgctxt "'Lat' and 'Lon' as in Latitude and Longitude"
|
||||
msgid "Lat: %1, Lon: %2"
|
||||
@@ -1194,7 +1194,7 @@ msgctxt "@action:button"
|
||||
msgid "Cancel reply"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/ChatBox/ChatBox.qml:60
|
||||
#: src/qml/Component/ChatBox/ChatBox.qml:64
|
||||
#, kde-format
|
||||
msgid "NeoChat is offline. Please check your network connection."
|
||||
msgstr ""
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2021-12-31 11:06-0800\n"
|
||||
"Last-Translator: A S Alam <aalam@satluj.org>\n"
|
||||
"Language-Team: Punjabi <punjabi-users@lists.sf.net>\n"
|
||||
@@ -131,91 +131,91 @@ msgstr "ਸੱਦਾ ਭੇਜੋ"
|
||||
msgid "Network Error"
|
||||
msgstr "ਨੈੱਟਵਰਕ ਗ਼ਲਤੀ"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "ਨਿਓ-ਚੈਟ"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "ਮੈਟਰਿਕਸ ਕਲਾਈਂਟ"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020-2021 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2021 KDE Community"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "ਕਾਰਲ ਸਚਵਾਨ"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "ਟੋਬਿਸ ਫੇਲਾ"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "ਅ.ਸ.ਆਲਮ ੨੦੨੧"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "alam.yellow@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr ""
|
||||
@@ -721,24 +721,24 @@ msgstr "<i>[ਇਹ ਸੁਨੇਹਾ ਹਟਾਇਆ ਗਿਆ ਸੀ]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[ਇਹ ਸੁਨੇਹਾ ਹਟਾਇਆ ਗਿਆ ਸੀ: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1688,22 +1688,22 @@ msgstr "ਲੋਕਲ ਫਾਇਲ ਚੁਣੋ"
|
||||
msgid "Clipboard image"
|
||||
msgstr "ਕਲਿੱਪਬੋਰਡ ਚਿੱਤਰ"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "ਪਹਿਲੇ ਨਾ-ਪੜ੍ਹੇ ਸੁਨੇਹੇ ਉੱਤੇ ਜਾਓ"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "ਸਭ ਤੋਂ ਨਵੇ ਸੁਨੇਹੇ ਉੱਤੇ ਜਾਓ"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-04-29 11:30+0200\n"
|
||||
"Last-Translator: Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>\n"
|
||||
"Language-Team: Polish <kde-i18n-doc@kde.org>\n"
|
||||
@@ -125,91 +125,91 @@ msgstr "Miejsce docelowe"
|
||||
msgid "Network Error"
|
||||
msgstr "Błąd sieci"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Klient Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2022 Społeczność KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Opiekun"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Czarny kapelusz"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Pierwotny autor Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Opiekun Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Karol Kosek, Łukasz Wojniłowicz"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "krkk@krkk.ct8.pl, lukasz.wojnilowicz@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Biblioteka Qt5 do pisania wieloplatformowych programów dla Matriksa"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (zbudowane na %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Program do obsługi protokołu matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Obsługuje matriksa: schemat url"
|
||||
@@ -658,17 +658,17 @@ msgstr "<i>[Wiadomość została usunięta]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Wiadomość została usunięta: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[ZREDAGOWANO]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[ZREDAGOWANO: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
@@ -676,7 +676,7 @@ msgstr[0] "1 użytkownik: "
|
||||
msgstr[1] "%1 użytkowników: "
|
||||
msgstr[2] "%1 użytkowników: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1598,22 +1598,22 @@ msgstr "Wybierz plik lokalny"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Obraz ze schowka"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Przeskocz do pierwszej nieprzeczytanej wiadomości"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Przeskocz do ostatniej wiadomości"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Przeciągnij tutaj elementy, aby je udostępnić"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -2,7 +2,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-09 23:16+0100\n"
|
||||
"Last-Translator: José Nuno Coelho Pires <zepires@gmail.com>\n"
|
||||
"Language-Team: Portuguese <kde-i18n-pt@kde.org>\n"
|
||||
@@ -126,91 +126,91 @@ msgstr "Destino"
|
||||
msgid "Network Error"
|
||||
msgstr "Erro de Rede"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Cliente do Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2023 da Comunidade do KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Manutenção"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Autor original do Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Manutenção do Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "José Nuno Pires"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "zepires@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
"Uma biblioteca do Qt5 para criar clientes multi-plataforma para o Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (compilado com a %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Cliente para o protocolo de comunicações Matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Suporta o esquema de URL's 'matrix:'"
|
||||
@@ -657,24 +657,24 @@ msgstr "<i>[Esta mensagem foi removida]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Esta mensagem foi removida: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[REDIGIDO]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[REDIGIDO: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "1 utilizador: "
|
||||
msgstr[1] "%1 utilizadores: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1584,22 +1584,22 @@ msgstr "Escolher um ficheiro local"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Imagem da área de transferência"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Ir para a primeira mensagem não-lida"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Ir para a última mensagem"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Arraste os itens para aqui para os partilhar"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-07 13:33-0300\n"
|
||||
"Last-Translator: Luiz Fernando Ranghetti <elchevive@opensuse.org>\n"
|
||||
"Language-Team: Brazilian Portuguese <kde-i18n-pt_BR@kde.org>\n"
|
||||
@@ -124,92 +124,92 @@ msgstr "Destino"
|
||||
msgid "Network Error"
|
||||
msgstr "Erro de rede"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Cliente Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2022 A comunidade KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Mantenedor"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Autor original do Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Mantenedor do Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Luiz Fernando Ranghetti, Thiago Masato Costa Sueto"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "elchevive@opensuse.org, herzenschein@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
"Uma biblioteca Qt5 para escrever clientes multiplataformas para o Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (compilado com %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Cliente para o protocolo de comunicação Matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Supports appstream: url scheme"
|
||||
msgid "Supports matrix: url scheme"
|
||||
@@ -718,24 +718,24 @@ msgstr "<i>[Esta mensagem foi excluída]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Esta mensagem foi excluída: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[CENSURADO]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[CENSURADO: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, fuzzy, kde-format
|
||||
#| msgctxt "[action 1], [action 2 and action 3]"
|
||||
#| msgid ", "
|
||||
@@ -1691,22 +1691,22 @@ msgstr "Escolher arquivo local"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Imagem da área de transferência"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Ir para primeira mensagem não lida"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Ir para a mensagem mais antiga"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Arraste itens aqui para compartilhar"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-04-27 15:01+0300\n"
|
||||
"Last-Translator: Olesya Gerasimenko <translation-team@basealt.ru>\n"
|
||||
"Language-Team: Basealt Translation Team\n"
|
||||
@@ -127,17 +127,17 @@ msgstr "Назначение"
|
||||
msgid "Network Error"
|
||||
msgstr "Ошибка соединения"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Клиент Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
@@ -145,75 +145,75 @@ msgstr ""
|
||||
"© Black Hat 2018-2020\n"
|
||||
"© Сообщество KDE 2020-2022"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Сопровождающий"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Первоначальный автор Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Алексей Русаков"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Сопровождающий Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Александр Яворский, Павел Чернышов, Олеся Герасименко"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "kekcuha@gmail.com, farline99@yandex.ru, translation-team@basealt.ru"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Библиотека Qt5 для написания кроссплатформенных клиентов Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (собрано с версией %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Клиент для протокола связи Matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Адрес, соответствующий схеме Matrix"
|
||||
@@ -666,17 +666,17 @@ msgstr "<i>[Это сообщение было удалено]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Cообщение было удалено: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[ОТРЕДАКТИРОВАНО]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[ОТРЕДАКТИРОВАНО: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
@@ -685,7 +685,7 @@ msgstr[1] "%1 пользователя: "
|
||||
msgstr[2] "%1 пользователей: "
|
||||
msgstr[3] "1 пользователь: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1611,22 +1611,22 @@ msgstr "Выберите файл на компьютере"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Изображение из буфера обмена"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Перейти к первому непрочитанному сообщению"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Перейти к последнему сообщению"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Чтобы опубликовать файла, перетащите их сюда"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -5,7 +5,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2022-04-18 17:58+0200\n"
|
||||
"Last-Translator: Roman Paholik <wizzardsk@gmail.com>\n"
|
||||
"Language-Team: Slovak <kde-sk@linux.sk>\n"
|
||||
@@ -130,91 +130,91 @@ msgstr "Odoslať pozvanie"
|
||||
msgid "Network Error"
|
||||
msgstr "Chyba siete"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix client"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020 KDE komunita"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Roman Paholík"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "wizzardsk@gmail.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Klient pre komunikačný protokol matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Supports appstream: url scheme"
|
||||
msgid "Supports matrix: url scheme"
|
||||
@@ -743,17 +743,17 @@ msgstr "<i>[Táto správa bola odstránená]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Táto správa bola odstránená: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[REVIDOVANÉ]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[REVIDOVANÉ: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
@@ -761,7 +761,7 @@ msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, fuzzy, kde-format
|
||||
#| msgctxt "[action 1], [action 2 and action 3]"
|
||||
#| msgid ", "
|
||||
@@ -1719,22 +1719,22 @@ msgstr "Vybrať miestny súbor"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Obrázok schránky"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Skočiť na prvú neprečítanú správu"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Prejsť na najnovšiu správu"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Presuňte položky sem na zdieľanie"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-09 08:30+0200\n"
|
||||
"Last-Translator: Matjaž Jeran <matjaz.jeran@amis.net>\n"
|
||||
"Language-Team: Slovenian <lugos-slo@lugos.si>\n"
|
||||
@@ -124,90 +124,90 @@ msgstr "Cilj"
|
||||
msgid "Network Error"
|
||||
msgstr "Napaka omrežja"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrixov odjemalec"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2023 skupnost KDE"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Vzdrževalec"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Izvorni avtor programa Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Vzdrževalec programa Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Matjaž Jeran,Martin Srebotnjak"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "matjaz.jeran@amis.net,miles@filmsi.net"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Knjižnica Qt5 za pisanje odjemalcev za več platform za Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (zgrajeno na %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Odjemalec za komunikacijski protokol matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Podpira matriko: shema url"
|
||||
@@ -656,17 +656,17 @@ msgstr "<i>[To sporočilo je bilo izbrisano]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[To sporočilo je bilo izbrisano: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[PREKRIVANJE PODATKOV]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[PREKRIVANJE PODATKOV: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
@@ -675,7 +675,7 @@ msgstr[1] "%1 uporabnika: "
|
||||
msgstr[2] "%1 uporabniki: "
|
||||
msgstr[3] "%1 uporabnikov: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1590,22 +1590,22 @@ msgstr "Izberi lokalno datoteko"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Slika odložišča"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Skoči na prvo neprebrano sporočilo"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Skoči na nedavno sporočilo"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Povleci predmete sem, da jih deliš z drugimi"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2022-09-28 16:37+0200\n"
|
||||
"Last-Translator: Stefan Asserhäll <stefan.asserhall@bredband.net>\n"
|
||||
"Language-Team: Swedish <kde-i18n-doc@kde.org>\n"
|
||||
@@ -130,91 +130,91 @@ msgstr "Skicka inbjudan"
|
||||
msgid "Network Error"
|
||||
msgstr "Nätverksfel"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix-klient"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "© 2018-2020 Black Hat, 2020-2022 KDE Community"
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2022 KDE-gemenskapen"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Stefan Asserhäll"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "stefan.asserhall@bredband.net"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Att Qt5-bibliotek för att skriva Matrix-klienter för flera plattformar"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Klient för kommunikationsprotokollet Matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Supports appstream: url scheme"
|
||||
msgid "Supports matrix: url scheme"
|
||||
@@ -740,24 +740,24 @@ msgstr "<i>[Meddelandet har tagits bort]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Meddelandet har tagits bort: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[ÄNDRAD]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[ÄNDRAD: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, fuzzy, kde-format
|
||||
#| msgctxt "[action 1], [action 2 and action 3]"
|
||||
#| msgid ", "
|
||||
@@ -1713,22 +1713,22 @@ msgstr "Välj lokal fil"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Klippbordsbild"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Gå till första olästa meddelande"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Gå till sista meddelande"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Dra objekt hit för att dela dem"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-11 17:29+0530\n"
|
||||
"Last-Translator: Kishore G <kishore96@gmail.com>\n"
|
||||
"Language-Team: Tamil <kde-i18n-doc@kde.org>\n"
|
||||
@@ -123,90 +123,90 @@ msgstr "சேருமிடம்"
|
||||
msgid "Network Error"
|
||||
msgstr "பிணைய சிக்கல்"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "நியோச்சாட்"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix வாங்கி"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 பிளாக் ஹாட், 2020-2023 கே.டீ.யீ. சமூகம்"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "கார்ல் ஷுவான்"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "பராமரிப்பாளர்"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "டோபியாஸ் ஃபெல்லா"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "ஜேம்சு கிரஹாம்"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "பிளாக் ஹாட்"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Spectral-ஐ முதலில் இயற்றியவர்"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "அலெக்செய் ருசாக்கொவ்"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Quotient-இன் பராமரிப்பாளர்"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "கோ. கிஷோர்"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "Kde-l10n-ta@kde.org"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "மேட்ரிக்ஸுக்கான பல்லியங்குதள செயலிகளை எழுத உதவும் Qt5 நிரலகம்"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (%2 கொண்டு தொகுக்கப்பட்டது)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Matrix தொடர்பு நெறிமுறைக்கான வாங்கி"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "matrix: முகவரி திட்டமுறையை ஆதரிக்கும்"
|
||||
@@ -653,24 +653,24 @@ msgstr "<i>[இந்த செய்தி நீக்கப்பட்டத
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[இந்த செய்தி நீக்கப்பட்டது: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[தணிக்கை செய்யப்பட்டது]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[தணிக்கை செய்யப்பட்டது: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "1 பயனர்: "
|
||||
msgstr[1] "%1 பயனர்கள்: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1579,22 +1579,22 @@ msgstr "உள்ளமைக் கோப்பைத் தேர்ந்த
|
||||
msgid "Clipboard image"
|
||||
msgstr "பிடிப்புப்பலகைப் படம்"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "படிக்காத முதல் செய்திக்குத் தாவு"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "கடைசி செய்திக்குத் தாவு"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "எதையாவது பகிர, அதை இங்கு இழுத்துப் போடுங்கள்"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2022-06-20 03:30+0000\n"
|
||||
"Last-Translator: Weblate Admin <admin@example.com>\n"
|
||||
"Language-Team: Toki Pona <http://weblate.blackquill.cc/projects/ante-toki-pi-"
|
||||
@@ -129,90 +129,90 @@ msgstr ""
|
||||
msgid "Network Error"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "kulupu pi ante toki pi toki pona"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr ""
|
||||
@@ -675,17 +675,17 @@ msgstr ""
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
@@ -694,7 +694,7 @@ msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
msgstr[3] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1623,22 +1623,22 @@ msgstr ""
|
||||
msgid "Clipboard image"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-09 12:30+0300\n"
|
||||
"Last-Translator: Emir SARI <emir_sari@icloud.com>\n"
|
||||
"Language-Team: Turkish <kde-l10n-tr@kde.org>\n"
|
||||
@@ -123,90 +123,90 @@ msgstr "Hedef"
|
||||
msgid "Network Error"
|
||||
msgstr "Ağ Hatası"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix istemcisi"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© 2018-2020 Black Hat, 2020-2023 KDE Topluluğu"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Bakımcı"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Spectral'in özgün yazarı"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Aleksey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Quotient bakımcısı"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Emir SARI"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "emir_sari@icloud.com"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "Matrix için çapraz platform istemciler yazmak için bir Qt5 kitaplığı"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (%2 üzerine yapılı)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Matrix iletişim protokolü için istemci"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "matrix: URL şemasını destekler"
|
||||
@@ -651,24 +651,24 @@ msgstr "<i>[Bu ileti silindi]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Bu ileti silindi: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[DEĞİŞTİRİLDİ]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[DEĞİŞTİRİLDİ: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] "%1 kullanıcı: "
|
||||
msgstr[1] "%1 kullanıcı: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1576,22 +1576,22 @@ msgstr "Yerel dosya seçin"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Pano görseli"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "İlk okunmamış iletiye atla"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "En son iletiye atla"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Onları paylaşmak için ögeleri buraya sürükleyin"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-06-09 17:30+0300\n"
|
||||
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
|
||||
"Language-Team: Ukrainian <kde-i18n-uk@kde.org>\n"
|
||||
@@ -127,92 +127,92 @@ msgstr "Призначення"
|
||||
msgid "Network Error"
|
||||
msgstr "Помилка у мережі"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Клієнт Matrix"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr "© Black Hat, 2018-2020, Спільнота KDE, 2020–2023"
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "Супровідник"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Перший автор Spectral"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Супровідник Quotient"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Юрій Чорноіван"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "yurchor@ukr.net"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
"Бібліотека Qt5 для написання багатоплатформових клієнтських програм для "
|
||||
"Matrix"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (зібрано з %2)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Клієнт для протоколу обміну даними matrix"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "Передбачає підтримку схеми адрес matrix:"
|
||||
@@ -663,17 +663,17 @@ msgstr "<i>[Це повідомлення було вилучено]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[Це повідомлення було вилучено: %1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr "[ЗМІНЕНО]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr "[ЗМІНЕНО: %1]"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
@@ -682,7 +682,7 @@ msgstr[1] "%1 користувачі: "
|
||||
msgstr[2] "%1 користувачів: "
|
||||
msgstr[3] "%1 користувач: "
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1600,22 +1600,22 @@ msgstr "Виберіть локальний файл"
|
||||
msgid "Clipboard image"
|
||||
msgstr "Зображення з буфера"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "Перейти до першого непрочитаного повідомлення"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "Перейти до останнього повідомлення"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "Перетягніть пункти сюди, щоб оприлюднити їх"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -2,7 +2,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: kdeorg\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2023-05-22 14:01\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
@@ -125,62 +125,62 @@ msgstr ""
|
||||
msgid "Network Error"
|
||||
msgstr "网络错误"
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr "NeoChat"
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr "Matrix 客户端"
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr "Carl Schwan"
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr "维护人员"
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr "Tobias Fella"
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr "James Graham"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr "Black Hat"
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr "Spectral 的原作者"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr "Alexey Rusakov"
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr "Quotient 的维护人员"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
@@ -188,7 +188,7 @@ msgstr ""
|
||||
"KDE China (中国), Guo Yunhe (郭云鹤), Yang Boyuan (杨博远), Coelacanthus, "
|
||||
"Tyson Tan (钛山), Gary Wang"
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
@@ -196,23 +196,23 @@ msgstr ""
|
||||
"kde-china@kde.org, i@guoyunhe.me, 073plan@gmail.com, coelacanthus@kde.org, "
|
||||
"tysontan@tysontan.com, git@blumia.net"
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr "一个用于编写跨平台 Matrix 客户端的 Qt5 库"
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr "%1 (使用 %2 构建)"
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr "Matrix 通信协议客户端"
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr "支持 matrix: URL 协议"
|
||||
@@ -656,23 +656,23 @@ msgstr "<i>[这条消息已被删除]</i>"
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr "<i>[这条消息已被删除:%1]</i>"
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1575,22 +1575,22 @@ msgstr "选择本地文件"
|
||||
msgid "Clipboard image"
|
||||
msgstr "剪贴板图像"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr "跳转到第一条未读消息"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr "跳转到最新消息"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr "拖动项目到此处来分享"
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -9,7 +9,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: neochat\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:47+0000\n"
|
||||
"POT-Creation-Date: 2023-06-17 00:48+0000\n"
|
||||
"PO-Revision-Date: 2022-12-30 18:05+0900\n"
|
||||
"Last-Translator: Kisaragi Hiu <mail@kisaragi-hiu.com>\n"
|
||||
"Language-Team: Traditional Chinese <zh-l10n@linux.org.tw>\n"
|
||||
@@ -124,90 +124,90 @@ msgstr ""
|
||||
msgid "Network Error"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:161
|
||||
#: src/main.cpp:162
|
||||
#, kde-format
|
||||
msgid "NeoChat"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:163
|
||||
#: src/main.cpp:164
|
||||
#, kde-format
|
||||
msgid "Matrix client"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:165
|
||||
#: src/main.cpp:166
|
||||
#, kde-format
|
||||
msgid "© 2018-2020 Black Hat, 2020-2023 KDE Community"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:166
|
||||
#: src/main.cpp:167
|
||||
#, kde-format
|
||||
msgid "Carl Schwan"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:166 src/main.cpp:167 src/main.cpp:168
|
||||
#: src/main.cpp:167 src/main.cpp:168 src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "Maintainer"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:167
|
||||
#: src/main.cpp:168
|
||||
#, kde-format
|
||||
msgid "Tobias Fella"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:168
|
||||
#: src/main.cpp:169
|
||||
#, kde-format
|
||||
msgid "James Graham"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Black Hat"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:169
|
||||
#: src/main.cpp:170
|
||||
#, kde-format
|
||||
msgid "Original author of Spectral"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Alexey Rusakov"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:170
|
||||
#: src/main.cpp:171
|
||||
#, kde-format
|
||||
msgid "Maintainer of Quotient"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:171
|
||||
#: src/main.cpp:172
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:175
|
||||
#: src/main.cpp:176
|
||||
#, kde-format
|
||||
msgid "A Qt5 library to write cross-platform clients for Matrix"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:178
|
||||
#: src/main.cpp:179
|
||||
#, kde-format
|
||||
msgctxt "<version number> (built against <possibly different version number>)"
|
||||
msgid "%1 (built against %2)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:324
|
||||
#: src/main.cpp:326
|
||||
#, kde-format
|
||||
msgid "Client for the matrix communication protocol"
|
||||
msgstr ""
|
||||
|
||||
#: src/main.cpp:325
|
||||
#: src/main.cpp:327
|
||||
#, kde-format
|
||||
msgid "Supports matrix: url scheme"
|
||||
msgstr ""
|
||||
@@ -650,23 +650,23 @@ msgstr ""
|
||||
msgid "<i>[This message was deleted: %1]</i>"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:553
|
||||
#: src/models/messageeventmodel.cpp:556
|
||||
#, kde-format
|
||||
msgid "[REDACTED: %1]"
|
||||
msgstr ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:862
|
||||
#: src/models/messageeventmodel.cpp:870
|
||||
#, kde-format
|
||||
msgid "1 user: "
|
||||
msgid_plural "%1 users: "
|
||||
msgstr[0] ""
|
||||
|
||||
#: src/models/messageeventmodel.cpp:869
|
||||
#: src/models/messageeventmodel.cpp:877
|
||||
#, kde-format
|
||||
msgctxt "list separator"
|
||||
msgid ", "
|
||||
@@ -1569,22 +1569,22 @@ msgstr ""
|
||||
msgid "Clipboard image"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:202
|
||||
#: src/qml/Component/TimelineView.qml:203
|
||||
#, kde-format
|
||||
msgid "Jump to first unread message"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:225
|
||||
#: src/qml/Component/TimelineView.qml:226
|
||||
#, kde-format
|
||||
msgid "Jump to latest message"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:251
|
||||
#: src/qml/Component/TimelineView.qml:252
|
||||
#, kde-format
|
||||
msgid "Drag items here to share them"
|
||||
msgstr ""
|
||||
|
||||
#: src/qml/Component/TimelineView.qml:277
|
||||
#: src/qml/Component/TimelineView.qml:278
|
||||
#, kde-format
|
||||
msgctxt "Message displayed when some users are typing"
|
||||
msgid "%2 is typing"
|
||||
|
||||
@@ -56,6 +56,7 @@ add_library(neochat STATIC
|
||||
events/stickerevent.cpp
|
||||
models/reactionmodel.cpp
|
||||
delegatesizehelper.cpp
|
||||
models/livelocationsmodel.cpp
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(neochat
|
||||
@@ -65,12 +66,6 @@ ecm_qt_declare_logging_category(neochat
|
||||
DEFAULT_SEVERITY Info
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(neochat
|
||||
HEADER "voip_logging.h"
|
||||
IDENTIFIER "voip"
|
||||
CATEGORY_NAME "org.kde.neochat.voip"
|
||||
)
|
||||
|
||||
add_executable(neochat-app
|
||||
main.cpp
|
||||
res.qrc
|
||||
@@ -117,20 +112,6 @@ endif()
|
||||
|
||||
target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR})
|
||||
target_link_libraries(neochat PUBLIC Qt::Core Qt::Quick Qt::Qml Qt::Gui Qt::Multimedia Qt::Network Qt::QuickControls2 KF${QT_MAJOR_VERSION}::I18n KF${QT_MAJOR_VERSION}::Kirigami2 KF${QT_MAJOR_VERSION}::Notifications KF${QT_MAJOR_VERSION}::ConfigCore KF${QT_MAJOR_VERSION}::ConfigGui KF${QT_MAJOR_VERSION}::CoreAddons KF${QT_MAJOR_VERSION}::SonnetCore KF${QT_MAJOR_VERSION}::ItemModels Quotient${QUOTIENT_SUFFIX} cmark::cmark ${QTKEYCHAIN_LIBRARIES} QCoro::Core)
|
||||
|
||||
if (TARGET PkgConfig::GSTREAMER)
|
||||
target_link_libraries(neochat PUBLIC PkgConfig::GSTREAMER)
|
||||
target_sources(neochat PRIVATE
|
||||
call/callmanager.cpp
|
||||
call/callsession.cpp
|
||||
call/audiosources.cpp
|
||||
call/videosources.cpp
|
||||
call/devicemonitor.cpp
|
||||
models/callparticipantsmodel.cpp
|
||||
call/callparticipant.cpp
|
||||
)
|
||||
target_compile_definitions(neochat PUBLIC GSTREAMER_AVAILABLE)
|
||||
endif()
|
||||
kconfig_add_kcfg_files(neochat GENERATE_MOC neochatconfig.kcfgc)
|
||||
|
||||
if(NEOCHAT_FLATPAK)
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
#include "audiosources.h"
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
|
||||
#include "devicemonitor.h"
|
||||
|
||||
#include "neochatconfig.h"
|
||||
|
||||
int AudioSources::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return DeviceMonitor::instance().audioSources().size();
|
||||
}
|
||||
|
||||
QVariant AudioSources::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() >= DeviceMonitor::instance().audioSources().size()) {
|
||||
return QVariant(QStringLiteral("DEADBEEF"));
|
||||
}
|
||||
if (role == TitleRole) {
|
||||
return DeviceMonitor::instance().audioSources()[index.row()]->title;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> AudioSources::roleNames() const
|
||||
{
|
||||
return {
|
||||
{TitleRole, "title"},
|
||||
};
|
||||
}
|
||||
|
||||
AudioSources::AudioSources()
|
||||
: QAbstractListModel()
|
||||
{
|
||||
connect(&DeviceMonitor::instance(), &DeviceMonitor::audioSourceAdded, this, [this]() {
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
Q_EMIT currentIndexChanged();
|
||||
});
|
||||
connect(&DeviceMonitor::instance(), &DeviceMonitor::audioSourceRemoved, this, [this]() {
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
Q_EMIT currentIndexChanged();
|
||||
});
|
||||
}
|
||||
|
||||
GstDevice *AudioSources::currentDevice() const
|
||||
{
|
||||
const auto config = NeoChatConfig::self();
|
||||
const QString name = config->microphone();
|
||||
for (const auto &audioSource : DeviceMonitor::instance().audioSources()) {
|
||||
if (audioSource->title == name) {
|
||||
qDebug() << "WebRTC: microphone:" << name;
|
||||
return audioSource->device;
|
||||
}
|
||||
}
|
||||
return DeviceMonitor::instance().audioSources()[0]->device;
|
||||
}
|
||||
|
||||
void AudioSources::setCurrentIndex(int index) const
|
||||
{
|
||||
if (DeviceMonitor::instance().audioSources().size() == 0) {
|
||||
return;
|
||||
}
|
||||
NeoChatConfig::setMicrophone(DeviceMonitor::instance().audioSources()[index]->title);
|
||||
NeoChatConfig::self()->save();
|
||||
}
|
||||
|
||||
int AudioSources::currentIndex() const
|
||||
{
|
||||
const auto config = NeoChatConfig::self();
|
||||
const QString name = config->microphone();
|
||||
if (name.isEmpty()) {
|
||||
return getDefaultDeviceIndex();
|
||||
}
|
||||
for (auto i = 0; i < DeviceMonitor::instance().audioSources().size(); i++) {
|
||||
if (DeviceMonitor::instance().audioSources()[i]->title == name) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AudioSources::getDefaultDeviceIndex() const
|
||||
{
|
||||
for (auto i = 0; i < DeviceMonitor::instance().audioSources().size(); i++) {
|
||||
if (DeviceMonitor::instance().audioSources()[i]->isDefault) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QAbstractListModel>
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
class AudioSources : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
TitleRole = Qt::UserRole + 1,
|
||||
};
|
||||
|
||||
static AudioSources &instance()
|
||||
{
|
||||
static AudioSources _instance;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
GstDevice *currentDevice() const;
|
||||
|
||||
void setCurrentIndex(int index) const;
|
||||
int currentIndex() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void currentIndexChanged();
|
||||
|
||||
private:
|
||||
AudioSources();
|
||||
int getDefaultDeviceIndex() const;
|
||||
};
|
||||
@@ -1,199 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
||||
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "calldevices.h"
|
||||
#include "audiodevicesmodel.h"
|
||||
#include "neochatconfig.h"
|
||||
#include "videodevicesmodel.h"
|
||||
#include <QStringView>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
|
||||
#include "voiplogging.h"
|
||||
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
extern "C" {
|
||||
#include "gst/gst.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
|
||||
CallDevices::CallDevices()
|
||||
: QObject()
|
||||
, m_audioDevicesModel(new AudioDevicesModel(this))
|
||||
, m_videoDevicesModel(new VideoDevicesModel(this))
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
AudioDevicesModel *CallDevices::audioDevicesModel() const
|
||||
{
|
||||
return m_audioDevicesModel;
|
||||
}
|
||||
|
||||
VideoDevicesModel *CallDevices::videoDevicesModel() const
|
||||
{
|
||||
return m_videoDevicesModel;
|
||||
}
|
||||
|
||||
void CallDevices::addDevice(GstDevice *device)
|
||||
{
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
gchar *type = gst_device_get_device_class(device);
|
||||
bool isVideo = !std::strncmp(type, "Video", 5);
|
||||
g_free(type);
|
||||
if (isVideo) {
|
||||
m_videoDevicesModel->addDevice(device);
|
||||
m_videoDevicesModel->setDefaultDevice();
|
||||
} else {
|
||||
m_audioDevicesModel->addDevice(device);
|
||||
m_audioDevicesModel->setDefaultDevice();
|
||||
}
|
||||
}
|
||||
|
||||
void CallDevices::removeDevice(GstDevice *device, bool changed)
|
||||
{
|
||||
if (device) {
|
||||
if (m_audioDevicesModel->removeDevice(device, changed) || m_videoDevicesModel->removeDevice(device, changed))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
gboolean newBusMessage(GstBus *bus, GstMessage *msg, gpointer user_data)
|
||||
{
|
||||
Q_UNUSED(bus)
|
||||
Q_UNUSED(user_data)
|
||||
|
||||
switch (GST_MESSAGE_TYPE(msg)) {
|
||||
case GST_MESSAGE_DEVICE_ADDED: {
|
||||
GstDevice *device;
|
||||
gst_message_parse_device_added(msg, &device);
|
||||
CallDevices::instance().addDevice(device);
|
||||
Q_EMIT CallDevices::instance().devicesChanged();
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_DEVICE_REMOVED: {
|
||||
GstDevice *device;
|
||||
gst_message_parse_device_removed(msg, &device);
|
||||
CallDevices::instance().removeDevice(device, false);
|
||||
Q_EMIT CallDevices::instance().devicesChanged();
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_DEVICE_CHANGED: {
|
||||
GstDevice *device;
|
||||
GstDevice *oldDevice;
|
||||
gst_message_parse_device_changed(msg, &device, &oldDevice);
|
||||
CallDevices::instance().removeDevice(oldDevice, true);
|
||||
CallDevices::instance().addDevice(device);
|
||||
Q_EMIT CallDevices::instance().devicesChanged();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CallDevices::init()
|
||||
{
|
||||
static GstDeviceMonitor *monitor = nullptr;
|
||||
if (!monitor) {
|
||||
monitor = gst_device_monitor_new();
|
||||
Q_ASSERT(monitor);
|
||||
GstCaps *caps = gst_caps_new_empty_simple("audio/x-raw");
|
||||
gst_device_monitor_add_filter(monitor, "Audio/Source", caps);
|
||||
gst_device_monitor_add_filter(monitor, "Audio/Duplex", caps);
|
||||
gst_caps_unref(caps);
|
||||
caps = gst_caps_new_empty_simple("video/x-raw");
|
||||
gst_device_monitor_add_filter(monitor, "Video/Source", caps);
|
||||
gst_device_monitor_add_filter(monitor, "Video/Duplex", caps);
|
||||
gst_caps_unref(caps);
|
||||
|
||||
GstBus *bus = gst_device_monitor_get_bus(monitor);
|
||||
gst_bus_add_watch(bus, newBusMessage, nullptr);
|
||||
gst_object_unref(bus);
|
||||
if (!gst_device_monitor_start(monitor)) {
|
||||
qCCritical(voip) << "Failed to start device monitor";
|
||||
return;
|
||||
} else {
|
||||
qCDebug(voip) << "Device monitor started";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CallDevices::hasMicrophone() const
|
||||
{
|
||||
return m_audioDevicesModel->hasMicrophone();
|
||||
}
|
||||
|
||||
bool CallDevices::hasCamera() const
|
||||
{
|
||||
return m_videoDevicesModel->hasCamera();
|
||||
}
|
||||
|
||||
QStringList CallDevices::resolutions(const QString &cameraName) const
|
||||
{
|
||||
return m_videoDevicesModel->resolutions(cameraName);
|
||||
}
|
||||
|
||||
QStringList CallDevices::frameRates(const QString &cameraName, const QString &resolution) const
|
||||
{
|
||||
if (auto s = m_videoDevicesModel->getVideoSource(cameraName); s) {
|
||||
if (auto it = std::find_if(s->caps.cbegin(),
|
||||
s->caps.cend(),
|
||||
[&](const auto &c) {
|
||||
return c.resolution == resolution;
|
||||
});
|
||||
it != s->caps.cend())
|
||||
return it->frameRates;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
GstDevice *CallDevices::audioDevice() const
|
||||
{
|
||||
return m_audioDevicesModel->currentDevice();
|
||||
}
|
||||
|
||||
GstDevice *CallDevices::videoDevice(QPair<int, int> &resolution, QPair<int, int> &frameRate) const
|
||||
{
|
||||
return m_videoDevicesModel->currentDevice(resolution, frameRate);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool CallDevices::hasMicrophone() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CallDevices::hasCamera() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList CallDevices::names(bool, const QString &) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
QStringList CallDevices::resolutions(const QString &) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
QStringList CallDevices::frameRates(const QString &, const QString &) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,64 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2021 Contributors
|
||||
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
typedef struct _GstDevice GstDevice;
|
||||
|
||||
class CallDevices;
|
||||
class AudioDevicesModel;
|
||||
class VideoDevicesModel;
|
||||
|
||||
class CallDevices : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(AudioDevicesModel *audioDevices READ audioDevicesModel CONSTANT);
|
||||
Q_PROPERTY(VideoDevicesModel *videoDevices READ videoDevicesModel CONSTANT);
|
||||
|
||||
public:
|
||||
static CallDevices &instance()
|
||||
{
|
||||
static CallDevices instance;
|
||||
return instance;
|
||||
}
|
||||
CallDevices(CallDevices const &) = delete;
|
||||
void operator=(CallDevices const &) = delete;
|
||||
|
||||
bool hasMicrophone() const;
|
||||
bool hasCamera() const;
|
||||
QStringList names(bool isVideo, const QString &defaultDevice) const;
|
||||
QStringList resolutions(const QString &cameraName) const;
|
||||
QStringList frameRates(const QString &cameraName, const QString &resolution) const;
|
||||
|
||||
AudioDevicesModel *audioDevicesModel() const;
|
||||
VideoDevicesModel *videoDevicesModel() const;
|
||||
|
||||
void addDevice(GstDevice *device);
|
||||
void removeDevice(GstDevice *device, bool changed);
|
||||
|
||||
Q_SIGNALS:
|
||||
void devicesChanged();
|
||||
|
||||
private:
|
||||
CallDevices();
|
||||
|
||||
void init();
|
||||
GstDevice *audioDevice() const;
|
||||
GstDevice *videoDevice(QPair<int, int> &resolution, QPair<int, int> &frameRate) const;
|
||||
|
||||
AudioDevicesModel *m_audioDevicesModel;
|
||||
VideoDevicesModel *m_videoDevicesModel;
|
||||
|
||||
friend class CallSession;
|
||||
friend class Audio;
|
||||
};
|
||||
@@ -1,617 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2020-2021 Nheko Authors
|
||||
// SPDX-FileCopyrightText: 2021-2023 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "callmanager.h"
|
||||
|
||||
#include "controller.h"
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "voiplogging.h"
|
||||
#include <KLocalizedString>
|
||||
#include <QDateTime>
|
||||
|
||||
#include <QMediaPlaylist>
|
||||
#include <QMimeDatabase>
|
||||
#include <qcoro/qcorosignal.h>
|
||||
#include <qt_connection_util.h>
|
||||
|
||||
#include "neochatconfig.h"
|
||||
|
||||
#define CALL_VERSION "1"
|
||||
|
||||
CallManager::CallManager()
|
||||
{
|
||||
init();
|
||||
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, [this] {
|
||||
updateTurnServers();
|
||||
});
|
||||
}
|
||||
|
||||
QCoro::Task<void> CallManager::updateTurnServers()
|
||||
{
|
||||
if (m_cachedTurnUrisValidUntil > QDateTime::currentDateTime()) {
|
||||
co_return;
|
||||
}
|
||||
Controller::instance().activeConnection()->getTurnServers();
|
||||
|
||||
auto servers = co_await qCoro(Controller::instance().activeConnection(), &Connection::turnServersChanged);
|
||||
m_cachedTurnUrisValidUntil = QDateTime::currentDateTime().addSecs(servers["ttl"].toInt());
|
||||
|
||||
const auto password = servers["password"].toString();
|
||||
const auto username = servers["username"].toString();
|
||||
const auto uris = servers["uris"].toArray();
|
||||
|
||||
m_cachedTurnUris.clear();
|
||||
for (const auto &u : uris) {
|
||||
QString uri = u.toString();
|
||||
auto c = uri.indexOf(':');
|
||||
if (c == -1) {
|
||||
qCWarning(voip) << "Invalid TURN URI:" << uri;
|
||||
continue;
|
||||
}
|
||||
QString scheme = uri.left(c);
|
||||
if (scheme != "turn" && scheme != "turns") {
|
||||
qCWarning(voip) << "Invalid TURN scheme:" << scheme;
|
||||
continue;
|
||||
}
|
||||
m_cachedTurnUris += QStringLiteral("%1://%2:%3@%4").arg(scheme, QUrl::toPercentEncoding(username), QUrl::toPercentEncoding(password), uri.mid(c + 1));
|
||||
}
|
||||
}
|
||||
|
||||
QString CallManager::callId() const
|
||||
{
|
||||
return m_callId;
|
||||
}
|
||||
|
||||
void CallManager::handleCallEvent(NeoChatRoom *room, const Quotient::RoomEvent *event)
|
||||
{
|
||||
if (const auto &inviteEvent = eventCast<const CallInviteEvent>(event)) {
|
||||
handleInvite(room, inviteEvent);
|
||||
} else if (const auto &hangupEvent = eventCast<const CallHangupEvent>(event)) {
|
||||
handleHangup(room, hangupEvent);
|
||||
} else if (const auto &candidatesEvent = eventCast<const CallCandidatesEvent>(event)) {
|
||||
handleCandidates(room, candidatesEvent);
|
||||
} else if (const auto &answerEvent = eventCast<const CallAnswerEvent>(event)) {
|
||||
handleAnswer(room, answerEvent);
|
||||
} else if (const auto &negotiateEvent = eventCast<const CallNegotiateEvent>(event)) {
|
||||
handleNegotiate(room, negotiateEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void CallManager::checkStartCall()
|
||||
{
|
||||
if ((m_incomingCandidates.isEmpty() && !m_incomingSdp.contains("candidates"_ls)) || m_incomingSdp.isEmpty()) {
|
||||
qCDebug(voip) << "Not ready to start this call yet";
|
||||
return;
|
||||
}
|
||||
m_session->acceptAnswer(m_incomingSdp, m_incomingCandidates, m_remoteUser->id());
|
||||
m_incomingCandidates.clear();
|
||||
m_incomingSdp.clear();
|
||||
setGlobalState(ACTIVE);
|
||||
}
|
||||
|
||||
void CallManager::handleAnswer(NeoChatRoom *room, const Quotient::CallAnswerEvent *event)
|
||||
{
|
||||
if (globalState() != OUTGOING) {
|
||||
qCDebug(voip) << "Ignoring answer while in state" << globalState();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->callId() != m_callId) {
|
||||
qCDebug(voip) << "Ignoring answer for unknown call id" << event->callId() << ". Our call id is" << m_callId;
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->senderId() == room->localUser()->id() && partyId() == event->contentJson()["party_id"].toString()) {
|
||||
qCDebug(voip) << "Ignoring echo for answer";
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->senderId() == room->localUser()->id()) {
|
||||
qCDebug(voip) << "Call was accepted on a different device";
|
||||
// Show the user that call was accepted on a different device
|
||||
// Stop ringing
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO handle that MSC wrt to accepting on other devices
|
||||
m_session->setMetadata(event->contentJson()["org.matrix.msc3077.sdp_stream_metadata"].toObject());
|
||||
m_remotePartyId = event->contentJson()["party_id"].toString();
|
||||
m_incomingSdp = event->sdp();
|
||||
checkStartCall();
|
||||
}
|
||||
|
||||
void CallManager::handleCandidates(NeoChatRoom *room, const Quotient::CallCandidatesEvent *event)
|
||||
{
|
||||
// TODO what if candidates come before invite? this looks wrong
|
||||
if (globalState() == IDLE) {
|
||||
qCDebug(voip) << "Ignoring candidates in state" << globalState();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->senderId() == room->localUser()->id()) {
|
||||
qCDebug(voip) << "Ignoring candidates sent by ourself";
|
||||
return;
|
||||
}
|
||||
|
||||
if (globalState() == ACTIVE) {
|
||||
QVector<Candidate> candidates;
|
||||
for (const auto &candidate : event->candidates()) {
|
||||
candidates += Candidate{candidate.toObject()["candidate"].toString(),
|
||||
candidate.toObject()["sdpMLineIndex"].toInt(),
|
||||
candidate.toObject()["sdpMid"].toString()};
|
||||
}
|
||||
m_session->acceptCandidates(candidates);
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(voip) << "Storing" << event->candidates().size() << "incoming candidates";
|
||||
for (const auto &candidate : event->candidates()) {
|
||||
m_incomingCandidates +=
|
||||
Candidate{candidate.toObject()["candidate"].toString(), candidate.toObject()["sdpMLineIndex"].toInt(), candidate.toObject()["sdpMid"].toString()};
|
||||
}
|
||||
|
||||
if (globalState() == OUTGOING) {
|
||||
checkStartCall();
|
||||
}
|
||||
}
|
||||
|
||||
void CallManager::handleInvite(NeoChatRoom *room, const Quotient::CallInviteEvent *event)
|
||||
{
|
||||
if (event->senderId() == room->localUser()->id()) {
|
||||
qCDebug(voip) << "Igoring invite sent by ourself";
|
||||
return;
|
||||
}
|
||||
if (globalState() != IDLE) {
|
||||
// TODO handle glare
|
||||
qCDebug(voip) << "Ignoring invite while already in a call";
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->originTimestamp() < QDateTime::currentDateTime().addSecs(-60)) {
|
||||
qCDebug(voip) << "Ignoring outdated invite; sent at:" << event->originTimestamp() << "current:" << QDateTime::currentDateTime();
|
||||
return;
|
||||
}
|
||||
|
||||
setGlobalState(INCOMING);
|
||||
|
||||
m_incomingSdp = event->sdp();
|
||||
setRemoteUser(dynamic_cast<NeoChatUser *>(room->user(event->senderId())));
|
||||
setRoom(room);
|
||||
setCallId(event->callId());
|
||||
setPartyId(generatePartyId());
|
||||
m_remotePartyId = event->contentJson()["party_id"].toString();
|
||||
setLifetime(event->lifetime());
|
||||
Q_EMIT incomingCall(remoteUser(), room, event->lifetime(), callId());
|
||||
ring(event->lifetime());
|
||||
}
|
||||
|
||||
void CallManager::handleNegotiate(NeoChatRoom *room, const Quotient::CallNegotiateEvent *event)
|
||||
{
|
||||
Q_UNUSED(room);
|
||||
if (event->callId() != m_callId) {
|
||||
qCDebug(voip) << "Ignoring negotiate for unknown call id" << event->callId() << ". Our call id is" << m_callId;
|
||||
return;
|
||||
}
|
||||
if (event->partyId() != m_remotePartyId) {
|
||||
qCDebug(voip) << "Ignoring negotiate for unknown party id" << event->partyId() << ". Remote party id is" << m_remotePartyId;
|
||||
return;
|
||||
}
|
||||
if (event->senderId() != m_remoteUser->id()) {
|
||||
qCDebug(voip) << "Ignoring negotiate for unknown user id" << event->senderId() << ". Remote user id is" << m_remoteUser->id();
|
||||
return;
|
||||
}
|
||||
// TODO DUPLICATES FFS
|
||||
m_session->setMetadata(event->contentJson()["org.matrix.msc3077.sdp_stream_metadata"].toObject());
|
||||
m_session->renegotiateOffer(event->sdp(), m_remoteUser->id(), event->contentJson()["description"]["type"] == QStringLiteral("answer"));
|
||||
}
|
||||
|
||||
void CallManager::ring(int lifetime)
|
||||
{
|
||||
// TODO put a better default ringtone in the kcfg
|
||||
// TODO which one? ship one? plasma-mobile-sounds?
|
||||
if (!QFileInfo::exists(NeoChatConfig::ringtone())) {
|
||||
qCWarning(voip) << "Ringtone file doesn't exist. Not audibly ringing";
|
||||
return;
|
||||
}
|
||||
auto ringtone = QUrl::fromLocalFile(NeoChatConfig::ringtone());
|
||||
m_playlist.setPlaybackMode(QMediaPlaylist::Loop);
|
||||
m_playlist.clear();
|
||||
m_ringPlayer.setPlaylist(&m_playlist);
|
||||
m_playlist.addMedia(ringtone);
|
||||
m_ringPlayer.play();
|
||||
QTimer::singleShot(lifetime, this, [this]() {
|
||||
stopRinging();
|
||||
Q_EMIT callEnded();
|
||||
});
|
||||
}
|
||||
|
||||
void CallManager::stopRinging()
|
||||
{
|
||||
m_ringPlayer.stop();
|
||||
}
|
||||
|
||||
void CallManager::handleHangup(NeoChatRoom *room, const Quotient::CallHangupEvent *event)
|
||||
{
|
||||
if (globalState() == IDLE) {
|
||||
qCDebug(voip) << "Ignoring hangup since we're not in a call";
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->senderId() == room->localUser()->id()) {
|
||||
qCDebug(voip) << "Ignoring hangup we sent ourselves";
|
||||
// TODO hangup-to-decline by different device?
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->callId() != m_callId) {
|
||||
qCDebug(voip) << "Hangup not for this call. Event's call id:" << event->callId() << ". Our call id" << m_callId;
|
||||
return;
|
||||
}
|
||||
|
||||
stopRinging();
|
||||
if (m_session) {
|
||||
m_session->end();
|
||||
delete m_session;
|
||||
}
|
||||
setGlobalState(IDLE);
|
||||
Q_EMIT callEnded();
|
||||
}
|
||||
|
||||
void CallManager::acceptCall()
|
||||
{
|
||||
// TODO metadata for this case
|
||||
if (globalState() != INCOMING) {
|
||||
qCWarning(voip) << "Not accepting call while state is" << globalState();
|
||||
return;
|
||||
}
|
||||
|
||||
stopRinging();
|
||||
|
||||
if (!checkPlugins()) {
|
||||
qCCritical(voip) << "Missing plugins; can't accept call";
|
||||
}
|
||||
|
||||
updateTurnServers();
|
||||
// TODO wait until candidates are here
|
||||
|
||||
m_session = CallSession::acceptCall(m_incomingSdp, m_incomingCandidates, m_cachedTurnUris, m_remoteUser->id(), this);
|
||||
m_participants->clear();
|
||||
connect(m_session.data(), &CallSession::stateChanged, this, [this] {
|
||||
Q_EMIT stateChanged();
|
||||
if (state() == CallSession::ICEFAILED) {
|
||||
Q_EMIT callEnded();
|
||||
}
|
||||
}); // TODO refactor away?
|
||||
m_incomingCandidates.clear();
|
||||
connectSingleShot(m_session.data(), &CallSession::answerCreated, this, [this](const QString &_sdp, const QVector<Candidate> &candidates) {
|
||||
const auto &[uuids, sdp] = mangleSdp(_sdp);
|
||||
QVector<std::pair<QString, QString>> msidToPurpose;
|
||||
for (const auto &uuid : uuids) {
|
||||
msidToPurpose += {uuid, "m.usermedia"}; // TODO
|
||||
}
|
||||
auto answer = createAnswer(m_callId, sdp, msidToPurpose);
|
||||
m_room->postJson("m.call.answer", answer);
|
||||
qCWarning(voip) << "Sending Answer";
|
||||
auto c = createCandidates(m_callId, candidates);
|
||||
auto cand = createCandidates(m_callId, candidates);
|
||||
m_room->postJson("m.call.candidates", cand);
|
||||
qCWarning(voip) << "Sending Candidates";
|
||||
setGlobalState(ACTIVE);
|
||||
});
|
||||
}
|
||||
|
||||
void CallManager::hangupCall()
|
||||
{
|
||||
qCDebug(voip) << "Ending call";
|
||||
if (m_session) {
|
||||
m_session->end();
|
||||
delete m_session;
|
||||
m_session = nullptr;
|
||||
}
|
||||
stopRinging();
|
||||
m_room->postJson("m.call.hangup", createHangup(m_callId));
|
||||
setGlobalState(IDLE);
|
||||
Q_EMIT callEnded();
|
||||
}
|
||||
|
||||
NeoChatUser *CallManager::remoteUser() const
|
||||
{
|
||||
return m_remoteUser;
|
||||
}
|
||||
|
||||
NeoChatRoom *CallManager::room() const
|
||||
{
|
||||
return m_room;
|
||||
}
|
||||
|
||||
CallSession::State CallManager::state() const
|
||||
{
|
||||
if (!m_session) {
|
||||
return CallSession::DISCONNECTED;
|
||||
}
|
||||
return m_session->state();
|
||||
}
|
||||
|
||||
int CallManager::lifetime() const
|
||||
{
|
||||
return m_lifetime;
|
||||
}
|
||||
|
||||
void CallManager::ignoreCall()
|
||||
{
|
||||
setLifetime(0);
|
||||
setCallId({});
|
||||
setRoom(nullptr);
|
||||
setRemoteUser(nullptr);
|
||||
}
|
||||
|
||||
void CallManager::startCall(NeoChatRoom *room)
|
||||
{
|
||||
if (m_session) {
|
||||
// Don't start calls if there already is one
|
||||
Q_EMIT Controller::instance().errorOccured(i18n("A call is already started"));
|
||||
return;
|
||||
}
|
||||
if (room->users().size() != 2) {
|
||||
// Don't start calls if the room doesn't have exactly two members
|
||||
Q_EMIT Controller::instance().errorOccured(i18n("Calls are limited to 1:1 rooms"));
|
||||
return;
|
||||
}
|
||||
|
||||
auto missingPlugins = CallSession::missingPlugins();
|
||||
if (!missingPlugins.isEmpty()) {
|
||||
qCCritical(voip) << "Missing GStreamer plugins:" << missingPlugins;
|
||||
Q_EMIT Controller::instance().errorOccured("Missing GStreamer plugins.");
|
||||
return;
|
||||
}
|
||||
|
||||
setLifetime(60000);
|
||||
setRoom(room);
|
||||
setRemoteUser(otherUser(room));
|
||||
|
||||
updateTurnServers();
|
||||
|
||||
setCallId(generateCallId());
|
||||
setPartyId(generatePartyId());
|
||||
|
||||
m_participants->clear();
|
||||
for (const auto &user : m_room->users()) {
|
||||
auto participant = new CallParticipant(m_session);
|
||||
participant->m_user = dynamic_cast<NeoChatUser *>(user);
|
||||
m_participants->addParticipant(participant);
|
||||
}
|
||||
|
||||
m_session = CallSession::startCall(m_cachedTurnUris, this);
|
||||
setGlobalState(OUTGOING);
|
||||
connect(m_session, &CallSession::stateChanged, this, [this] {
|
||||
Q_EMIT stateChanged();
|
||||
if (state() == CallSession::ICEFAILED) {
|
||||
Q_EMIT callEnded();
|
||||
}
|
||||
});
|
||||
|
||||
connectSingleShot(m_session.data(), &CallSession::offerCreated, this, [this](const QString &_sdp, const QVector<Candidate> &candidates) {
|
||||
const auto &[uuids, sdp] = mangleSdp(_sdp);
|
||||
QVector<std::pair<QString, QString>> msidToPurpose;
|
||||
for (const auto &uuid : uuids) {
|
||||
msidToPurpose += {uuid, "m.usermedia"}; // TODO
|
||||
}
|
||||
qCWarning(voip) << "Sending Invite";
|
||||
qCWarning(voip) << "Sending Candidates";
|
||||
auto invite = createInvite(m_callId, sdp, msidToPurpose);
|
||||
auto c = createCandidates(m_callId, candidates);
|
||||
m_room->postJson("m.call.invite", invite);
|
||||
m_room->postJson("m.call.candidates", c);
|
||||
});
|
||||
|
||||
connect(m_session, &CallSession::renegotiate, this, [this](const QString &sdp, const QString &type) {
|
||||
QVector<std::pair<QString, QString>> msidToPurpose;
|
||||
const auto &[uuids, _sdp] = mangleSdp(sdp);
|
||||
for (const auto &uuid : uuids) {
|
||||
msidToPurpose += {uuid, "m.usermedia"}; // TODO
|
||||
}
|
||||
QJsonObject json{
|
||||
{QStringLiteral("lifetime"), 60000},
|
||||
{QStringLiteral("version"), 1},
|
||||
{QStringLiteral("description"), QJsonObject{{QStringLiteral("type"), type}, {QStringLiteral("sdp"), _sdp}}}, // AAAAA
|
||||
{QStringLiteral("party_id"), m_partyId},
|
||||
{QStringLiteral("call_id"), m_callId},
|
||||
};
|
||||
QJsonObject metadata;
|
||||
for (const auto &[stream, purpose] : msidToPurpose) {
|
||||
QJsonObject data = {{"purpose", purpose}};
|
||||
metadata[stream] = data;
|
||||
}
|
||||
json["org.matrix.msc3077.sdp_stream_metadata"] = metadata;
|
||||
m_room->postJson("m.call.negotiate", json);
|
||||
});
|
||||
}
|
||||
|
||||
QString CallManager::generateCallId() const
|
||||
{
|
||||
return QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz");
|
||||
}
|
||||
|
||||
QString CallManager::generatePartyId() const
|
||||
{
|
||||
return QUuid::createUuid().toString();
|
||||
}
|
||||
|
||||
void CallManager::setCallId(const QString &callId)
|
||||
{
|
||||
m_callId = callId;
|
||||
Q_EMIT callIdChanged();
|
||||
}
|
||||
|
||||
void CallManager::setPartyId(const QString &partyId)
|
||||
{
|
||||
m_partyId = partyId;
|
||||
}
|
||||
|
||||
void CallManager::setMuted(bool muted)
|
||||
{
|
||||
if (!m_session) {
|
||||
return;
|
||||
}
|
||||
m_session->setMuted(muted);
|
||||
Q_EMIT mutedChanged();
|
||||
}
|
||||
|
||||
bool CallManager::muted() const
|
||||
{
|
||||
if (!m_session) {
|
||||
return false;
|
||||
}
|
||||
return m_session->muted();
|
||||
}
|
||||
|
||||
bool CallManager::init()
|
||||
{
|
||||
qRegisterMetaType<Candidate>();
|
||||
qRegisterMetaType<QVector<Candidate>>();
|
||||
GError *error = nullptr;
|
||||
if (!gst_init_check(nullptr, nullptr, &error)) {
|
||||
QString strError;
|
||||
if (error) {
|
||||
strError += error->message;
|
||||
g_error_free(error);
|
||||
}
|
||||
qCCritical(voip) << "Failed to initialize GStreamer:" << strError;
|
||||
return false;
|
||||
}
|
||||
|
||||
gchar *version = gst_version_string();
|
||||
qCDebug(voip) << "GStreamer version" << version;
|
||||
g_free(version);
|
||||
|
||||
// Required to register the qml types
|
||||
auto _sink = gst_element_factory_make("qmlglsink", nullptr);
|
||||
Q_ASSERT(_sink);
|
||||
gst_object_unref(_sink);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CallManager::setLifetime(int lifetime)
|
||||
{
|
||||
m_lifetime = lifetime;
|
||||
Q_EMIT lifetimeChanged();
|
||||
}
|
||||
|
||||
void CallManager::setRoom(NeoChatRoom *room)
|
||||
{
|
||||
m_room = room;
|
||||
Q_EMIT roomChanged();
|
||||
}
|
||||
|
||||
void CallManager::setRemoteUser(NeoChatUser *user)
|
||||
{
|
||||
m_remoteUser = user;
|
||||
Q_EMIT roomChanged();
|
||||
}
|
||||
|
||||
NeoChatUser *CallManager::otherUser(NeoChatRoom *room)
|
||||
{
|
||||
return dynamic_cast<NeoChatUser *>(room->users()[0]->id() == room->localUser()->id() ? room->users()[1] : room->users()[0]);
|
||||
}
|
||||
|
||||
QJsonObject CallManager::createCandidates(const QString &callId, const QVector<Candidate> &candidates) const
|
||||
{
|
||||
QJsonArray candidatesJson;
|
||||
for (const auto &candidate : candidates) {
|
||||
candidatesJson += QJsonObject{{"candidate", candidate.candidate}, {"sdpMid", candidate.sdpMid}, {"sdpMLineIndex", candidate.sdpMLineIndex}};
|
||||
}
|
||||
return QJsonObject{{"call_id", callId}, {"candidates", candidatesJson}, {"version", CALL_VERSION}, {"party_id", "todopartyid"}};
|
||||
}
|
||||
|
||||
void CallManager::setGlobalState(GlobalState globalState)
|
||||
{
|
||||
if (m_globalState == globalState) {
|
||||
return;
|
||||
}
|
||||
m_globalState = globalState;
|
||||
Q_EMIT globalStateChanged();
|
||||
}
|
||||
|
||||
CallManager::GlobalState CallManager::globalState() const
|
||||
{
|
||||
return m_globalState;
|
||||
}
|
||||
|
||||
CallParticipantsModel *CallManager::callParticipants() const
|
||||
{
|
||||
return m_participants;
|
||||
}
|
||||
|
||||
std::pair<QStringList, QString> CallManager::mangleSdp(const QString &_sdp)
|
||||
{
|
||||
QString sdp = _sdp;
|
||||
QRegularExpression regex("msid:user[0-9]+@host-[0-9a-f]+ webrtctransceiver([0-9])");
|
||||
auto iter = regex.globalMatch(sdp);
|
||||
QStringList uuids;
|
||||
|
||||
while (iter.hasNext()) {
|
||||
auto uuid = QUuid::createUuid();
|
||||
auto match = iter.next();
|
||||
uuids += uuid.toString();
|
||||
sdp.replace(match.captured(), QStringLiteral("msid:") + uuid.toString() + QStringLiteral(" foo"));
|
||||
}
|
||||
return {uuids, sdp};
|
||||
}
|
||||
|
||||
QJsonObject CallManager::createInvite(const QString &callId, const QString &sdp, const QVector<std::pair<QString, QString>> &msidToPurpose) const
|
||||
{
|
||||
QJsonObject metadata;
|
||||
for (const auto &[msid, purpose] : msidToPurpose) {
|
||||
metadata[msid] = QJsonObject{{"purpose", purpose}};
|
||||
}
|
||||
return {{"call_id", callId},
|
||||
{"party_id", "todopartyid"},
|
||||
{"lifetime", 60000},
|
||||
{"capabilities", QJsonObject{{"m.call.transferee", false}}},
|
||||
{"offer", QJsonObject{{"sdp", sdp}, {"type", "offer"}}},
|
||||
{"org.matrix.msc3077.sdp_stream_metadata", metadata},
|
||||
{"version", CALL_VERSION}};
|
||||
}
|
||||
|
||||
QJsonObject CallManager::createHangup(const QString &callId) const
|
||||
{
|
||||
return {{"call_id", callId}, {"party_id", "todopartyid"}, {"version", CALL_VERSION}};
|
||||
}
|
||||
|
||||
QJsonObject CallManager::createAnswer(const QString &callId, const QString &sdp, const QVector<std::pair<QString, QString>> &msidToPurpose) const
|
||||
{
|
||||
Q_ASSERT(!callId.isEmpty());
|
||||
QJsonObject metadata;
|
||||
for (const auto &[msid, purpose] : msidToPurpose) {
|
||||
metadata[msid] = QJsonObject{{"purpose", purpose}};
|
||||
}
|
||||
return {{"call_id", callId},
|
||||
{"party_id", "todopartyid"},
|
||||
{"lifetime", "lifetime"},
|
||||
{"capabilities", QJsonObject{{"m.call.transferee", false}}},
|
||||
{"offer", QJsonObject{{"sdp", sdp}, {"type", "offer"}}},
|
||||
{"org.matrix.msc3077.sdp_stream_metadata", metadata},
|
||||
{"version", CALL_VERSION}};
|
||||
}
|
||||
|
||||
void CallManager::toggleCamera()
|
||||
{
|
||||
m_session->toggleCamera();
|
||||
}
|
||||
QString CallManager::partyId() const
|
||||
{
|
||||
return m_partyId;
|
||||
}
|
||||
|
||||
bool CallManager::checkPlugins() const
|
||||
{
|
||||
auto missingPlugins = m_session->missingPlugins();
|
||||
if (!missingPlugins.isEmpty()) {
|
||||
qCCritical(voip) << "Missing GStreamer plugins:" << missingPlugins;
|
||||
Q_EMIT Controller::instance().errorOccured("Missing GStreamer plugins.");
|
||||
}
|
||||
return !missingPlugins.isEmpty();
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2020-2021 Nheko Authors
|
||||
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "neochatroom.h"
|
||||
#include "neochatuser.h"
|
||||
#include <QAbstractListModel>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <events/roomevent.h>
|
||||
|
||||
#include "callsession.h"
|
||||
|
||||
#include "models/callparticipantsmodel.h"
|
||||
#include <events/callevents.h>
|
||||
|
||||
#include <QMediaPlayer>
|
||||
#include <QMediaPlaylist>
|
||||
#include <QTimer>
|
||||
#include <qcoro/task.h>
|
||||
|
||||
#include <qobjectdefs.h>
|
||||
|
||||
class CallSession;
|
||||
class QQuickItem;
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
class CallManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum GlobalState {
|
||||
IDLE,
|
||||
INCOMING,
|
||||
OUTGOING,
|
||||
ACTIVE,
|
||||
};
|
||||
Q_ENUM(GlobalState);
|
||||
|
||||
Q_PROPERTY(GlobalState globalState READ globalState NOTIFY globalStateChanged)
|
||||
Q_PROPERTY(NeoChatUser *remoteUser READ remoteUser NOTIFY remoteUserChanged)
|
||||
Q_PROPERTY(QString callId READ callId NOTIFY callIdChanged)
|
||||
Q_PROPERTY(NeoChatRoom *room READ room NOTIFY roomChanged)
|
||||
Q_PROPERTY(int lifetime READ lifetime NOTIFY lifetimeChanged)
|
||||
Q_PROPERTY(bool muted READ muted WRITE setMuted NOTIFY mutedChanged)
|
||||
Q_PROPERTY(QQuickItem *item MEMBER m_item) // TODO allow for different devices for each session
|
||||
Q_PROPERTY(CallSession::State state READ state NOTIFY stateChanged)
|
||||
Q_PROPERTY(CallParticipantsModel *callParticipants READ callParticipants CONSTANT)
|
||||
|
||||
static CallManager &instance()
|
||||
{
|
||||
static CallManager _instance;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
[[nodiscard]] QString callId() const;
|
||||
[[nodiscard]] QString partyId() const;
|
||||
|
||||
CallSession::State state() const;
|
||||
|
||||
NeoChatUser *remoteUser() const;
|
||||
NeoChatRoom *room() const;
|
||||
|
||||
int lifetime() const;
|
||||
|
||||
bool muted() const;
|
||||
void setMuted(bool muted);
|
||||
|
||||
CallManager::GlobalState globalState() const;
|
||||
|
||||
void handleCallEvent(NeoChatRoom *room, const RoomEvent *event);
|
||||
|
||||
Q_INVOKABLE void startCall(NeoChatRoom *room);
|
||||
Q_INVOKABLE void acceptCall();
|
||||
Q_INVOKABLE void hangupCall();
|
||||
Q_INVOKABLE void ignoreCall();
|
||||
|
||||
Q_INVOKABLE void toggleCamera();
|
||||
|
||||
QCoro::Task<void> updateTurnServers();
|
||||
|
||||
[[nodiscard]] CallParticipantsModel *callParticipants() const;
|
||||
|
||||
QQuickItem *m_item = nullptr;
|
||||
|
||||
Q_SIGNALS:
|
||||
void currentCallIdChanged();
|
||||
void incomingCall(NeoChatUser *user, NeoChatRoom *room, int timeout, const QString &callId);
|
||||
void callEnded();
|
||||
void remoteUserChanged();
|
||||
void callIdChanged();
|
||||
void roomChanged();
|
||||
void stateChanged();
|
||||
void lifetimeChanged();
|
||||
void mutedChanged();
|
||||
void globalStateChanged();
|
||||
|
||||
private:
|
||||
CallManager();
|
||||
QString m_callId;
|
||||
|
||||
QVector<Candidate> m_incomingCandidates;
|
||||
QString m_incomingSdp;
|
||||
|
||||
[[nodiscard]] bool checkPlugins() const;
|
||||
|
||||
QStringList m_cachedTurnUris;
|
||||
QDateTime m_cachedTurnUrisValidUntil = QDateTime::fromSecsSinceEpoch(0);
|
||||
|
||||
NeoChatUser *m_remoteUser = nullptr;
|
||||
NeoChatRoom *m_room = nullptr;
|
||||
QString m_remotePartyId;
|
||||
QString m_partyId;
|
||||
int m_lifetime = 0;
|
||||
|
||||
GlobalState m_globalState = IDLE;
|
||||
|
||||
void handleInvite(NeoChatRoom *room, const CallInviteEvent *event);
|
||||
void handleHangup(NeoChatRoom *room, const CallHangupEvent *event);
|
||||
void handleCandidates(NeoChatRoom *room, const CallCandidatesEvent *event);
|
||||
void handleAnswer(NeoChatRoom *room, const CallAnswerEvent *event);
|
||||
void handleNegotiate(NeoChatRoom *room, const CallNegotiateEvent *event);
|
||||
void checkStartCall();
|
||||
|
||||
void ring(int lifetime);
|
||||
void stopRinging();
|
||||
|
||||
[[nodiscard]] QString generateCallId() const;
|
||||
[[nodiscard]] QString generatePartyId() const;
|
||||
bool init();
|
||||
|
||||
bool m_initialised = false;
|
||||
QPointer<CallSession> m_session = nullptr;
|
||||
|
||||
void setLifetime(int lifetime);
|
||||
void setRoom(NeoChatRoom *room);
|
||||
void setRemoteUser(NeoChatUser *user);
|
||||
void setCallId(const QString &callId);
|
||||
void setPartyId(const QString &partyId);
|
||||
void setGlobalState(GlobalState state);
|
||||
|
||||
std::pair<QStringList, QString> mangleSdp(const QString &sdp);
|
||||
|
||||
CallParticipantsModel *m_participants = new CallParticipantsModel();
|
||||
|
||||
NeoChatUser *otherUser(NeoChatRoom *room);
|
||||
|
||||
[[nodiscard]] QJsonObject createCandidates(const QString &callId, const QVector<Candidate> &candidates) const;
|
||||
[[nodiscard]] QJsonObject createInvite(const QString &callId, const QString &sdp, const QVector<std::pair<QString, QString>> &msidToPurpose) const;
|
||||
[[nodiscard]] QJsonObject createHangup(const QString &callId) const;
|
||||
[[nodiscard]] QJsonObject createAnswer(const QString &callId, const QString &sdp, const QVector<std::pair<QString, QString>> &msidToPurpose) const;
|
||||
|
||||
QMediaPlayer m_ringPlayer;
|
||||
QMediaPlaylist m_playlist;
|
||||
};
|
||||
@@ -1,51 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
#include "callnegotiateevent.h"
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
CallNegotiateEvent::CallNegotiateEvent(const QString &callId,
|
||||
const QString &partyId,
|
||||
int lifetime,
|
||||
const QString &sdp,
|
||||
bool answer,
|
||||
QVector<std::pair<QString, QString>> msidToPurpose)
|
||||
: EventTemplate(callId,
|
||||
{
|
||||
{QStringLiteral("lifetime"), lifetime},
|
||||
{QStringLiteral("version"), 1},
|
||||
{QStringLiteral("description"),
|
||||
QJsonObject{{QStringLiteral("type"), answer ? QStringLiteral("answer") : QStringLiteral("offer")}, {QStringLiteral("sdp"), sdp}}},
|
||||
{QStringLiteral("party_id"), partyId},
|
||||
})
|
||||
{
|
||||
QJsonObject metadata;
|
||||
for (const auto &[stream, purpose] : msidToPurpose) {
|
||||
QJsonObject data = {{"purpose", purpose}};
|
||||
metadata[stream] = purpose;
|
||||
}
|
||||
auto content = editJson();
|
||||
content["org.matrix.msc3077.sdp_stream_metadata"] = metadata;
|
||||
editJson()["content"] = content;
|
||||
}
|
||||
|
||||
CallNegotiateEvent::CallNegotiateEvent(const QJsonObject &json)
|
||||
: EventTemplate(json)
|
||||
{
|
||||
}
|
||||
|
||||
QString CallNegotiateEvent::partyId() const
|
||||
{
|
||||
return contentJson()["party_id"].toString();
|
||||
}
|
||||
|
||||
QString CallNegotiateEvent::sdp() const
|
||||
{
|
||||
return contentJson()["description"]["sdp"].toString();
|
||||
}
|
||||
|
||||
QJsonObject CallNegotiateEvent::sdpStreamMetadata() const
|
||||
{
|
||||
return contentJson()["org.matrix.msc3077.sdp_stream_metadata"].toObject();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <events/callevents.h>
|
||||
|
||||
namespace Quotient
|
||||
{
|
||||
|
||||
class CallNegotiateEvent : public EventTemplate<CallNegotiateEvent, CallEvent>
|
||||
{
|
||||
public:
|
||||
QUO_EVENT(CallNegotiateEvent, "m.call.negotiate")
|
||||
|
||||
explicit CallNegotiateEvent(const QJsonObject &obj);
|
||||
|
||||
explicit CallNegotiateEvent(const QString &callId,
|
||||
const QString &partyId,
|
||||
int lifetime,
|
||||
const QString &sdp,
|
||||
bool answer,
|
||||
QVector<std::pair<QString, QString>> msidToPurpose);
|
||||
|
||||
QString partyId() const;
|
||||
QString sdp() const;
|
||||
// TODO make this a struct instead
|
||||
QJsonObject sdpStreamMetadata() const;
|
||||
};
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "callparticipant.h"
|
||||
|
||||
NeoChatUser *CallParticipant::user() const
|
||||
{
|
||||
return m_user;
|
||||
}
|
||||
|
||||
bool CallParticipant::hasCamera() const
|
||||
{
|
||||
return m_hasCamera;
|
||||
}
|
||||
|
||||
CallParticipant::CallParticipant(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void CallParticipant::initCamera(QQuickItem *item)
|
||||
{
|
||||
QTimer::singleShot(500, this, [=] {
|
||||
Q_EMIT initialized(item);
|
||||
});
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include "neochatuser.h"
|
||||
|
||||
class QQuickItem;
|
||||
|
||||
class CallParticipant : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(NeoChatUser *user READ user CONSTANT)
|
||||
Q_PROPERTY(bool hasCamera READ hasCamera NOTIFY hasCameraChanged)
|
||||
|
||||
public:
|
||||
NeoChatUser *m_user = nullptr;
|
||||
bool m_hasCamera = false;
|
||||
|
||||
Q_INVOKABLE void initCamera(QQuickItem *item);
|
||||
|
||||
[[nodiscard]] NeoChatUser *user() const;
|
||||
|
||||
[[nodiscard]] bool hasCamera() const;
|
||||
|
||||
explicit CallParticipant(QObject *parent = nullptr);
|
||||
|
||||
Q_SIGNALS:
|
||||
void initialized(QQuickItem *item);
|
||||
void heightChanged();
|
||||
void widthChanged();
|
||||
void hasCameraChanged();
|
||||
};
|
||||
@@ -1,916 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
||||
// SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu>
|
||||
// SPDX-FileCopyrightText: 2021-2022 Tobias Fella <fella@posteo.de>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "calldevices.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#define GST_USE_UNSTABLE_API
|
||||
#include <gst/webrtc/webrtc.h>
|
||||
#undef GST_USE_UNSTABLE_API
|
||||
|
||||
#include "voiplogging.h"
|
||||
|
||||
#include "audiosources.h"
|
||||
#include "videosources.h"
|
||||
|
||||
#include <qcoro/qcorosignal.h>
|
||||
|
||||
#define private public
|
||||
#include "callsession.h"
|
||||
#undef private
|
||||
#include "callmanager.h"
|
||||
#include <qt_connection_util.h>
|
||||
|
||||
#define STUN_SERVER "stun://turn.matrix.org:3478" // TODO make STUN server configurable
|
||||
|
||||
#define INSTANCE \
|
||||
Q_ASSERT(user_data); \
|
||||
auto instance = static_cast<CallSession *>(user_data);
|
||||
|
||||
GstElement *createElement(const char *type, GstElement *pipe, const char *name = nullptr)
|
||||
{
|
||||
auto element = gst_element_factory_make(type, name);
|
||||
Q_ASSERT_X(element, __FUNCTION__, QStringLiteral("Failed to create element %1 %2").arg(type, name).toLatin1());
|
||||
if (pipe) {
|
||||
gst_bin_add_many(GST_BIN(pipe), element, nullptr);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
GstElement *binGetByName(GstElement *bin, const char *name)
|
||||
{
|
||||
auto element = gst_bin_get_by_name(GST_BIN(bin), name);
|
||||
Q_ASSERT_X(element, __FUNCTION__, QStringLiteral("Failed to get element by name: %1").arg(name).toLatin1());
|
||||
return element;
|
||||
}
|
||||
|
||||
struct KeyFrameRequestData {
|
||||
GstElement *pipe = nullptr;
|
||||
GstElement *decodeBin = nullptr;
|
||||
gint packetsLost = 0;
|
||||
guint timerId = 0;
|
||||
QString statsField;
|
||||
} keyFrameRequestData;
|
||||
|
||||
std::pair<int, int> getResolution(GstPad *pad)
|
||||
{
|
||||
std::pair<int, int> ret;
|
||||
auto caps = gst_pad_get_current_caps(pad);
|
||||
auto structure = gst_caps_get_structure(caps, 0);
|
||||
gst_structure_get_int(structure, "width", &ret.first);
|
||||
gst_structure_get_int(structure, "height", &ret.second);
|
||||
gst_caps_unref(caps);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::pair<int, int> getResolution(GstElement *pipe, const gchar *elementName, const gchar *padName)
|
||||
{
|
||||
auto element = binGetByName(pipe, elementName);
|
||||
auto pad = gst_element_get_static_pad(element, padName);
|
||||
auto ret = getResolution(pad);
|
||||
gst_object_unref(pad);
|
||||
gst_object_unref(element);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void setLocalDescription(GstPromise *promise, gpointer user_data)
|
||||
{
|
||||
INSTANCE
|
||||
qCDebug(voip) << "Setting local description";
|
||||
const GstStructure *reply = gst_promise_get_reply(promise);
|
||||
gboolean isAnswer = gst_structure_id_has_field(reply, g_quark_from_string("answer"));
|
||||
GstWebRTCSessionDescription *gstsdp = nullptr;
|
||||
gst_structure_get(reply, isAnswer ? "answer" : "offer", GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &gstsdp, nullptr);
|
||||
gst_promise_unref(promise);
|
||||
auto webrtcbin = binGetByName(instance->m_pipe, "webrtcbin");
|
||||
Q_ASSERT(gstsdp);
|
||||
g_signal_emit_by_name(webrtcbin, "set-local-description", gstsdp, nullptr);
|
||||
gchar *sdp = gst_sdp_message_as_text(gstsdp->sdp);
|
||||
if (!instance->m_localSdp.isEmpty()) {
|
||||
// This is a renegotiation
|
||||
qWarning() << "emitting renegotiate";
|
||||
Q_EMIT instance->renegotiate(QString(sdp), isAnswer ? QStringLiteral("answer") : QStringLiteral("offer"));
|
||||
}
|
||||
instance->m_localSdp = QString(sdp);
|
||||
g_free(sdp);
|
||||
gst_webrtc_session_description_free(gstsdp);
|
||||
qCDebug(voip) << "Local description set:" << isAnswer;
|
||||
}
|
||||
|
||||
bool contains(std::string_view str1, std::string_view str2)
|
||||
{
|
||||
return std::search(str1.cbegin(),
|
||||
str1.cend(),
|
||||
str2.cbegin(),
|
||||
str2.cend(),
|
||||
[](unsigned char c1, unsigned char c2) {
|
||||
return std::tolower(c1) == std::tolower(c2);
|
||||
})
|
||||
!= str1.cend();
|
||||
}
|
||||
|
||||
void createOffer(GstElement *webrtc, CallSession *session)
|
||||
{
|
||||
// TODO ?!?
|
||||
if (!session->m_localSdp.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
qCWarning(voip) << "Creating Offer";
|
||||
auto promise = gst_promise_new_with_change_func(setLocalDescription, session, nullptr);
|
||||
g_signal_emit_by_name(webrtc, "create-offer", nullptr, promise);
|
||||
}
|
||||
|
||||
void createAnswer(GstPromise *promise, gpointer user_data)
|
||||
{
|
||||
INSTANCE
|
||||
qCDebug(voip) << "Creating Answer";
|
||||
gst_promise_unref(promise);
|
||||
promise = gst_promise_new_with_change_func(setLocalDescription, instance, nullptr);
|
||||
auto webrtcbin = binGetByName(instance->m_pipe, "webrtcbin");
|
||||
g_signal_emit_by_name(webrtcbin, "create-answer", nullptr, promise);
|
||||
}
|
||||
|
||||
bool getMediaAttributes(const GstSDPMessage *sdp, const char *mediaType, const char *encoding, int &payloadType, bool &receiveOnly, bool &sendOnly)
|
||||
{
|
||||
payloadType = -1;
|
||||
receiveOnly = false;
|
||||
sendOnly = false;
|
||||
for (guint mlineIndex = 0; mlineIndex < gst_sdp_message_medias_len(sdp); mlineIndex++) {
|
||||
const GstSDPMedia *media = gst_sdp_message_get_media(sdp, mlineIndex);
|
||||
if (!strcmp(gst_sdp_media_get_media(media), mediaType)) {
|
||||
receiveOnly = gst_sdp_media_get_attribute_val(media, "recvonly") != nullptr;
|
||||
sendOnly = gst_sdp_media_get_attribute_val(media, "sendonly") != nullptr;
|
||||
const gchar *rtpval = nullptr;
|
||||
for (guint n = 0; n == 0 || rtpval; n++) {
|
||||
rtpval = gst_sdp_media_get_attribute_val_n(media, "rtpmap", n);
|
||||
if (rtpval && contains(rtpval, encoding)) {
|
||||
payloadType = QString::fromLatin1(rtpval).toInt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
GstWebRTCSessionDescription *parseSDP(const QString &sdp, GstWebRTCSDPType type)
|
||||
{
|
||||
GstSDPMessage *message;
|
||||
gst_sdp_message_new(&message);
|
||||
if (gst_sdp_message_parse_buffer((guint8 *)sdp.toLatin1().data(), sdp.size(), message) == GST_SDP_OK) {
|
||||
return gst_webrtc_session_description_new(type, message);
|
||||
} else {
|
||||
qCCritical(voip) << "Failed to parse remote SDP";
|
||||
gst_sdp_message_free(message);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void addLocalICECandidate(GstElement *webrtc, guint mlineIndex, const gchar *candidate, gpointer user_data)
|
||||
{
|
||||
Q_UNUSED(webrtc);
|
||||
INSTANCE
|
||||
// qCWarning(voip) << "Adding local ICE Candidates";
|
||||
instance->m_localCandidates += Candidate{candidate, static_cast<int>(mlineIndex), QString()};
|
||||
}
|
||||
|
||||
void iceConnectionStateChanged(GstElement *webrtc, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
Q_UNUSED(pspec);
|
||||
INSTANCE
|
||||
GstWebRTCICEConnectionState newState;
|
||||
g_object_get(webrtc, "ice-connection-state", &newState, nullptr);
|
||||
switch (newState) {
|
||||
case GST_WEBRTC_ICE_CONNECTION_STATE_NEW:
|
||||
case GST_WEBRTC_ICE_CONNECTION_STATE_CHECKING:
|
||||
instance->setState(CallSession::CONNECTING);
|
||||
break;
|
||||
case GST_WEBRTC_ICE_CONNECTION_STATE_FAILED:
|
||||
instance->setState(CallSession::ICEFAILED);
|
||||
break;
|
||||
case GST_WEBRTC_ICE_CONNECTION_STATE_CONNECTED:
|
||||
instance->setState(CallSession::CONNECTED);
|
||||
case GST_WEBRTC_ICE_CONNECTION_STATE_COMPLETED:
|
||||
case GST_WEBRTC_ICE_CONNECTION_STATE_DISCONNECTED:
|
||||
case GST_WEBRTC_ICE_CONNECTION_STATE_CLOSED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GstElement *newAudioSinkChain(GstElement *pipe)
|
||||
{
|
||||
qCWarning(voip) << "New Audio Sink Chain";
|
||||
GstElement *queue = createElement("queue", pipe);
|
||||
GstElement *convert = createElement("audioconvert", pipe);
|
||||
GstElement *resample = createElement("audioresample", pipe);
|
||||
GstElement *sink = createElement("autoaudiosink", pipe);
|
||||
gst_element_link_many(queue, convert, resample, sink, nullptr);
|
||||
gst_element_sync_state_with_parent(queue);
|
||||
gst_element_sync_state_with_parent(convert);
|
||||
gst_element_sync_state_with_parent(resample);
|
||||
gst_element_sync_state_with_parent(sink);
|
||||
return queue;
|
||||
}
|
||||
|
||||
void sendKeyFrameRequest()
|
||||
{
|
||||
auto sinkpad = gst_element_get_static_pad(keyFrameRequestData.decodeBin, "sink");
|
||||
if (!gst_pad_push_event(sinkpad, gst_event_new_custom(GST_EVENT_CUSTOM_UPSTREAM, gst_structure_new_empty("GstForceKeyUnit")))) {
|
||||
qCWarning(voip) << "Keyframe request failed";
|
||||
}
|
||||
gst_object_unref(sinkpad);
|
||||
}
|
||||
|
||||
void onGetStats(GstPromise *promise, gpointer)
|
||||
{
|
||||
auto reply = gst_promise_get_reply(promise);
|
||||
GstStructure *rtpStats;
|
||||
if (!gst_structure_get(reply, keyFrameRequestData.statsField.toLatin1().data(), GST_TYPE_STRUCTURE, &rtpStats, nullptr)) {
|
||||
gst_promise_unref(promise);
|
||||
return;
|
||||
}
|
||||
auto packetsLost = 0;
|
||||
gst_structure_get_int(rtpStats, "packets-lost", &packetsLost);
|
||||
gst_structure_free(rtpStats);
|
||||
gst_promise_unref(promise);
|
||||
if (packetsLost > keyFrameRequestData.packetsLost) {
|
||||
qCWarning(voip) << "inbound video lost packet count:" << packetsLost;
|
||||
keyFrameRequestData.packetsLost = packetsLost;
|
||||
sendKeyFrameRequest();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO port to QTimer?
|
||||
gboolean testPacketLoss(gpointer)
|
||||
{
|
||||
if (!keyFrameRequestData.pipe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto webrtc = binGetByName(keyFrameRequestData.pipe, "webrtcbin");
|
||||
auto promise = gst_promise_new_with_change_func(onGetStats, nullptr, nullptr);
|
||||
g_signal_emit_by_name(webrtc, "get-stats", nullptr, promise);
|
||||
gst_object_unref(webrtc);
|
||||
return true;
|
||||
}
|
||||
|
||||
GstElement *newVideoSinkChain(GstElement *pipe, QQuickItem *quickItem)
|
||||
{
|
||||
Q_ASSERT(pipe);
|
||||
Q_ASSERT(quickItem);
|
||||
qCWarning(voip) << "Creating Video Sink Chain";
|
||||
auto queue = createElement("queue", pipe);
|
||||
auto compositor = createElement("compositor", pipe);
|
||||
auto glupload = createElement("glupload", pipe);
|
||||
auto glcolorconvert = createElement("glcolorconvert", pipe);
|
||||
auto qmlglsink = createElement("qmlglsink", nullptr);
|
||||
auto glsinkbin = createElement("glsinkbin", pipe);
|
||||
g_object_set(qmlglsink, "widget", quickItem, nullptr);
|
||||
g_object_set(glsinkbin, "sink", qmlglsink, nullptr);
|
||||
gst_element_link_many(queue, compositor, glupload, glcolorconvert, glsinkbin, nullptr);
|
||||
gst_element_sync_state_with_parent(queue);
|
||||
gst_element_sync_state_with_parent(compositor);
|
||||
gst_element_sync_state_with_parent(glupload);
|
||||
gst_element_sync_state_with_parent(glcolorconvert);
|
||||
gst_element_sync_state_with_parent(glsinkbin);
|
||||
return queue;
|
||||
}
|
||||
|
||||
static GstPadProbeReturn pad_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
|
||||
{
|
||||
Q_UNUSED(pad);
|
||||
// auto stream = static_cast<VideoStream *>(user_data);
|
||||
auto event = GST_PAD_PROBE_INFO_EVENT(info);
|
||||
if (GST_EVENT_CAPS == GST_EVENT_TYPE(event)) {
|
||||
GstCaps *caps = gst_caps_new_any();
|
||||
int width, height;
|
||||
gst_event_parse_caps(event, &caps);
|
||||
auto structure = gst_caps_get_structure(caps, 0);
|
||||
gst_structure_get_int(structure, "width", &width);
|
||||
gst_structure_get_int(structure, "height", &height);
|
||||
// stream->setWidth(width);
|
||||
// stream->setHeight(height);
|
||||
// TODO needed?
|
||||
}
|
||||
return GST_PAD_PROBE_OK;
|
||||
}
|
||||
|
||||
void linkNewPad(GstElement *decodeBin, GstPad *newpad, gpointer user_data)
|
||||
{
|
||||
INSTANCE
|
||||
qCWarning(voip) << "Linking New Pad";
|
||||
auto sinkpad = gst_element_get_static_pad(decodeBin, "sink");
|
||||
auto sinkcaps = gst_pad_get_current_caps(sinkpad);
|
||||
auto structure = gst_caps_get_structure(sinkcaps, 0);
|
||||
|
||||
gchar *mediaType = nullptr;
|
||||
guint ssrc = 0;
|
||||
gst_structure_get(structure, "media", G_TYPE_STRING, &mediaType, "ssrc", G_TYPE_UINT, &ssrc, nullptr);
|
||||
gst_caps_unref(sinkcaps);
|
||||
gst_object_unref(sinkpad);
|
||||
|
||||
GstElement *queue = nullptr;
|
||||
if (!strcmp(mediaType, "audio")) {
|
||||
qCWarning(voip) << "Receiving audio stream";
|
||||
queue = newAudioSinkChain(instance->m_pipe);
|
||||
} else if (!strcmp(mediaType, "video")) {
|
||||
qCWarning(voip) << "Receiving video stream";
|
||||
auto fake = createElement("fakesink", instance->m_pipe);
|
||||
auto selector = createElement("output-selector", instance->m_pipe);
|
||||
auto selectorSink = gst_element_get_static_pad(selector, "sink");
|
||||
auto selectorSrc1 = gst_element_request_pad_simple(selector, "src_%u");
|
||||
gst_pad_link(newpad, selectorSink);
|
||||
auto fakepad = gst_element_get_static_pad(fake, "sink");
|
||||
gst_pad_link(selectorSrc1, fakepad);
|
||||
g_object_set(selector, "active-pad", selectorSrc1, nullptr);
|
||||
|
||||
auto msid = instance->ssrcToMsid[ssrc];
|
||||
|
||||
// gst_pad_add_probe(newpad, GST_PAD_PROBE_TYPE_EVENT_BOTH, pad_cb, stream, nullptr);
|
||||
auto manager = dynamic_cast<CallManager *>(instance->parent());
|
||||
auto participants = manager->callParticipants();
|
||||
auto user = dynamic_cast<NeoChatUser *>(manager->room()->user(instance->msidToUserId[msid]));
|
||||
participants->setHasCamera(user, true);
|
||||
|
||||
auto participant = participants->callParticipantForUser(user);
|
||||
|
||||
// gst_pad_add_probe(newpad, GST_PAD_PROBE_TYPE_EVENT_BOTH, pad_cb, nullptr, nullptr);
|
||||
connectSingleShot(participant, &CallParticipant::initialized, instance, [=](QQuickItem *item) {
|
||||
gst_pad_unlink(newpad, fakepad);
|
||||
auto queue = newVideoSinkChain(instance->m_pipe, item);
|
||||
auto queuepad = gst_element_get_static_pad(queue, "sink");
|
||||
Q_ASSERT(queuepad);
|
||||
auto selectorSrc = gst_element_request_pad_simple(selector, "src_%u");
|
||||
auto ok = GST_PAD_LINK_SUCCESSFUL(gst_pad_link(selectorSrc, queuepad));
|
||||
Q_ASSERT(ok);
|
||||
g_object_set(selector, "active-pad", selectorSrc, nullptr);
|
||||
instance->setState(CallSession::CONNECTED);
|
||||
keyFrameRequestData.pipe = instance->m_pipe;
|
||||
keyFrameRequestData.decodeBin = decodeBin;
|
||||
keyFrameRequestData.timerId = g_timeout_add_seconds(3, testPacketLoss, nullptr);
|
||||
keyFrameRequestData.statsField = QStringLiteral("rtp-inbound-stream-stats_") + QString::number(ssrc);
|
||||
gst_object_unref(queuepad);
|
||||
g_free(mediaType);
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
g_free(mediaType);
|
||||
qCWarning(voip) << "Unknown pad type:" << GST_PAD_NAME(newpad);
|
||||
return;
|
||||
}
|
||||
auto queuepad = gst_element_get_static_pad(queue, "sink");
|
||||
Q_ASSERT(queuepad);
|
||||
auto ok = GST_PAD_LINK_SUCCESSFUL(gst_pad_link(newpad, queuepad));
|
||||
Q_ASSERT(ok);
|
||||
gst_object_unref(queuepad);
|
||||
g_free(mediaType);
|
||||
}
|
||||
|
||||
void setWaitForKeyFrame(GstBin *decodeBin, GstElement *element, gpointer)
|
||||
{
|
||||
Q_UNUSED(decodeBin);
|
||||
if (!strcmp(gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(gst_element_get_factory(element))), "rtpvp8depay")) {
|
||||
g_object_set(element, "wait-for-keyframe", TRUE, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void addDecodeBin(GstElement *webrtc, GstPad *newpad, gpointer user_data)
|
||||
{
|
||||
Q_UNUSED(webrtc);
|
||||
if (GST_PAD_DIRECTION(newpad) != GST_PAD_SRC) {
|
||||
return;
|
||||
}
|
||||
|
||||
INSTANCE
|
||||
|
||||
auto decodeBin = createElement("decodebin", instance->m_pipe);
|
||||
// Investigate hardware, see nheko source
|
||||
g_object_set(decodeBin, "force-sw-decoders", TRUE, nullptr);
|
||||
g_signal_connect(decodeBin, "pad-added", G_CALLBACK(linkNewPad), instance);
|
||||
g_signal_connect(decodeBin, "element-added", G_CALLBACK(setWaitForKeyFrame), nullptr);
|
||||
gst_element_sync_state_with_parent(decodeBin);
|
||||
auto sinkpad = gst_element_get_static_pad(decodeBin, "sink");
|
||||
if (GST_PAD_LINK_FAILED(gst_pad_link(newpad, sinkpad))) {
|
||||
// TODO: Error handling
|
||||
qCWarning(voip) << "Unable to link decodebin";
|
||||
}
|
||||
gst_object_unref(sinkpad);
|
||||
}
|
||||
|
||||
void iceGatheringStateChanged(GstElement *webrtc, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
Q_UNUSED(pspec);
|
||||
INSTANCE
|
||||
|
||||
GstWebRTCICEGatheringState newState;
|
||||
g_object_get(webrtc, "ice-gathering-state", &newState, nullptr);
|
||||
if (newState == GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE) {
|
||||
qCWarning(voip) << "GstWebRTCICEGatheringState -> Complete";
|
||||
if (instance->m_isOffering) {
|
||||
Q_EMIT instance->offerCreated(instance->m_localSdp, instance->m_localCandidates);
|
||||
instance->setState(CallSession::OFFERSENT);
|
||||
} else {
|
||||
Q_EMIT instance->answerCreated(instance->m_localSdp, instance->m_localCandidates);
|
||||
instance->setState(CallSession::ANSWERSENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean newBusMessage(GstBus *bus, GstMessage *msg, gpointer user_data)
|
||||
{
|
||||
Q_UNUSED(bus);
|
||||
INSTANCE
|
||||
|
||||
switch (GST_MESSAGE_TYPE(msg)) {
|
||||
case GST_MESSAGE_EOS:
|
||||
qCWarning(voip) << "End of stream";
|
||||
// TODO: Error handling
|
||||
instance->end();
|
||||
break;
|
||||
case GST_MESSAGE_ERROR:
|
||||
GError *error;
|
||||
gchar *debug;
|
||||
gst_message_parse_error(msg, &error, &debug);
|
||||
qCWarning(voip) << "Error from element:" << GST_OBJECT_NAME(msg->src) << error->message;
|
||||
// TODO: Error handling
|
||||
g_clear_error(&error);
|
||||
g_free(debug);
|
||||
instance->end();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CallSession::CallSession(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void CallSession::acceptAnswer(const QString &sdp, const QVector<Candidate> &candidates, const QString &userId)
|
||||
{
|
||||
qCDebug(voip) << "Accepting Answer";
|
||||
if (m_state != CallSession::OFFERSENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
GstWebRTCSessionDescription *answer = parseSDP(sdp, GST_WEBRTC_SDP_TYPE_ANSWER);
|
||||
if (!answer) {
|
||||
end();
|
||||
return;
|
||||
}
|
||||
|
||||
acceptCandidates(candidates);
|
||||
|
||||
setRemoteDescription(answer, userId);
|
||||
}
|
||||
|
||||
void CallSession::setRemoteDescription(GstWebRTCSessionDescription *remote, const QString &userId, GstPromise *promise)
|
||||
{
|
||||
GstElement *webrtcbin = binGetByName(m_pipe, "webrtcbin");
|
||||
auto sdp = remote->sdp;
|
||||
for (guint i = 0; i < gst_sdp_message_medias_len(sdp); i++) {
|
||||
auto media = gst_sdp_message_get_media(sdp, i);
|
||||
QList<uint32_t> ssrcs;
|
||||
QString msid;
|
||||
for (guint j = 0; j < gst_sdp_media_attributes_len(media); j++) {
|
||||
auto attribute = gst_sdp_media_get_attribute(media, j);
|
||||
if (!strcmp(attribute->key, "ssrc")) {
|
||||
ssrcs += QString(attribute->value).split(" ")[0].toUInt();
|
||||
}
|
||||
if (!strcmp(attribute->key, "msid")) {
|
||||
msid = QString(attribute->value).split(" ")[0];
|
||||
}
|
||||
}
|
||||
for (const auto &ssrc : ssrcs) {
|
||||
ssrcToMsid[ssrc] = msid;
|
||||
}
|
||||
msidToUserId[msid] = userId;
|
||||
}
|
||||
g_signal_emit_by_name(webrtcbin, "set-remote-description", remote, promise);
|
||||
}
|
||||
|
||||
void CallSession::renegotiateOffer(const QString &_offer, const QString &userId, bool answer)
|
||||
{
|
||||
GstWebRTCSessionDescription *sdp = parseSDP(_offer, answer ? GST_WEBRTC_SDP_TYPE_ANSWER : GST_WEBRTC_SDP_TYPE_OFFER);
|
||||
if (!sdp) {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
GstElement *webrtcbin = binGetByName(m_pipe, "webrtcbin");
|
||||
|
||||
setRemoteDescription(sdp, userId);
|
||||
qWarning() << "answer:" << answer;
|
||||
if (!answer) {
|
||||
GstPromise *promise = gst_promise_new_with_change_func(setLocalDescription, this, nullptr);
|
||||
g_signal_emit_by_name(webrtcbin, "create-answer", nullptr, promise);
|
||||
}
|
||||
}
|
||||
|
||||
void CallSession::acceptOffer(const QString &sdp, const QVector<Candidate> remoteCandidates, const QString &userId)
|
||||
{
|
||||
Q_ASSERT(!sdp.isEmpty());
|
||||
Q_ASSERT(!remoteCandidates.isEmpty());
|
||||
qCDebug(voip) << "Accepting offer";
|
||||
if (m_state != CallSession::DISCONNECTED) {
|
||||
return;
|
||||
}
|
||||
m_isOffering = false;
|
||||
|
||||
GstWebRTCSessionDescription *offer = parseSDP(sdp, GST_WEBRTC_SDP_TYPE_OFFER);
|
||||
if (!offer) {
|
||||
qCCritical(voip) << "Not an offer";
|
||||
return;
|
||||
}
|
||||
|
||||
int opusPayloadType;
|
||||
bool receiveOnly;
|
||||
bool sendOnly;
|
||||
if (getMediaAttributes(offer->sdp, "audio", "opus", opusPayloadType, receiveOnly, sendOnly)) {
|
||||
if (opusPayloadType == -1) {
|
||||
qCCritical(voip) << "No OPUS in offer";
|
||||
gst_webrtc_session_description_free(offer);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
qCCritical(voip) << "No audio in offer";
|
||||
gst_webrtc_session_description_free(offer);
|
||||
return;
|
||||
}
|
||||
startPipeline();
|
||||
|
||||
QThread::msleep(1000); // ?
|
||||
|
||||
acceptCandidates(remoteCandidates);
|
||||
|
||||
auto promise = gst_promise_new_with_change_func(createAnswer, this, nullptr);
|
||||
setRemoteDescription(offer, userId, promise);
|
||||
gst_webrtc_session_description_free(offer);
|
||||
}
|
||||
|
||||
void CallSession::createCall()
|
||||
{
|
||||
qCDebug(voip) << "Creating call";
|
||||
m_isOffering = true;
|
||||
startPipeline();
|
||||
}
|
||||
|
||||
void CallSession::startPipeline()
|
||||
{
|
||||
qCDebug(voip) << "Starting Pipeline";
|
||||
if (m_state != CallSession::DISCONNECTED) {
|
||||
return;
|
||||
}
|
||||
m_state = CallSession::INITIATING;
|
||||
Q_EMIT stateChanged();
|
||||
|
||||
createPipeline();
|
||||
|
||||
auto webrtcbin = binGetByName(m_pipe, "webrtcbin");
|
||||
Q_ASSERT(webrtcbin);
|
||||
if (false /*TODO: CHECK USE STUN*/) {
|
||||
qCDebug(voip) << "Setting STUN server:" << STUN_SERVER;
|
||||
g_object_set(webrtcbin, "stun-server", STUN_SERVER, nullptr);
|
||||
}
|
||||
|
||||
for (const auto &uri : m_turnServers) {
|
||||
qCDebug(voip) << "Setting turn server:" << uri;
|
||||
gboolean udata;
|
||||
g_signal_emit_by_name(webrtcbin, "add-turn-server", uri.toLatin1().data(), (gpointer)(&udata));
|
||||
}
|
||||
|
||||
if (m_turnServers.empty()) {
|
||||
qCWarning(voip) << "No TURN servers provided";
|
||||
}
|
||||
|
||||
if (m_isOffering) {
|
||||
g_signal_connect(webrtcbin, "on-negotiation-needed", G_CALLBACK(::createOffer), this);
|
||||
}
|
||||
|
||||
g_signal_connect(webrtcbin, "on-ice-candidate", G_CALLBACK(addLocalICECandidate), this);
|
||||
g_signal_connect(webrtcbin, "notify::ice-connection-state", G_CALLBACK(iceConnectionStateChanged), this);
|
||||
|
||||
gst_element_set_state(m_pipe, GST_STATE_READY);
|
||||
g_signal_connect(webrtcbin, "pad-added", G_CALLBACK(addDecodeBin), this);
|
||||
|
||||
g_signal_connect(webrtcbin, "notify::ice-gathering-state", G_CALLBACK(iceGatheringStateChanged), this);
|
||||
gst_object_unref(webrtcbin);
|
||||
|
||||
GstStateChangeReturn ret = gst_element_set_state(m_pipe, GST_STATE_PLAYING);
|
||||
if (ret == GST_STATE_CHANGE_FAILURE) {
|
||||
// TODO: Error handling
|
||||
qCCritical(voip) << "Unable to start pipeline";
|
||||
end();
|
||||
return;
|
||||
}
|
||||
|
||||
GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipe));
|
||||
m_busWatchId = gst_bus_add_watch(bus, newBusMessage, this);
|
||||
gst_object_unref(bus);
|
||||
|
||||
m_state = CallSession::INITIATED;
|
||||
Q_EMIT stateChanged();
|
||||
}
|
||||
|
||||
void CallSession::end()
|
||||
{
|
||||
qCDebug(voip) << "Ending Call";
|
||||
if (m_pipe) {
|
||||
gst_element_set_state(m_pipe, GST_STATE_NULL);
|
||||
gst_object_unref(m_pipe);
|
||||
m_pipe = nullptr;
|
||||
keyFrameRequestData.pipe = nullptr;
|
||||
if (m_busWatchId) {
|
||||
g_source_remove(m_busWatchId);
|
||||
m_busWatchId = 0;
|
||||
}
|
||||
}
|
||||
if (m_state != CallSession::DISCONNECTED) {
|
||||
m_state = CallSession::DISCONNECTED;
|
||||
Q_EMIT stateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void CallSession::createPipeline()
|
||||
{
|
||||
qCWarning(voip) << "Creating Pipeline";
|
||||
auto device = AudioSources::instance().currentDevice();
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
m_pipe = gst_pipeline_new(nullptr);
|
||||
auto source = gst_device_create_element(device, nullptr);
|
||||
auto volume = createElement("volume", m_pipe, "srclevel");
|
||||
auto convert = createElement("audioconvert", m_pipe);
|
||||
auto resample = createElement("audioresample", m_pipe);
|
||||
auto queue1 = createElement("queue", m_pipe);
|
||||
auto opusenc = createElement("opusenc", m_pipe);
|
||||
auto rtp = createElement("rtpopuspay", m_pipe);
|
||||
auto queue2 = createElement("queue", m_pipe);
|
||||
auto capsfilter = createElement("capsfilter", m_pipe);
|
||||
|
||||
auto rtpcaps = gst_caps_new_simple("application/x-rtp",
|
||||
"media",
|
||||
G_TYPE_STRING,
|
||||
"audio",
|
||||
"encoding-name",
|
||||
G_TYPE_STRING,
|
||||
"OPUS",
|
||||
"payload",
|
||||
G_TYPE_INT,
|
||||
OPUS_PAYLOAD_TYPE,
|
||||
nullptr);
|
||||
Q_ASSERT(rtpcaps);
|
||||
g_object_set(capsfilter, "caps", rtpcaps, nullptr);
|
||||
gst_caps_unref(rtpcaps);
|
||||
|
||||
auto webrtcbin = createElement("webrtcbin", m_pipe, "webrtcbin");
|
||||
g_object_set(webrtcbin, "bundle-policy", GST_WEBRTC_BUNDLE_POLICY_MAX_BUNDLE, nullptr);
|
||||
|
||||
gst_bin_add_many(GST_BIN(m_pipe), source, nullptr);
|
||||
|
||||
if (!gst_element_link_many(source, volume, convert, resample, queue1, opusenc, rtp, queue2, capsfilter, webrtcbin, nullptr)) {
|
||||
qCCritical(voip) << "Failed to link pipeline";
|
||||
// TODO propagate errors up and end call
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CallSession::toggleCamera()
|
||||
{
|
||||
// TODO do this only once
|
||||
static bool inited = false;
|
||||
if (!inited) {
|
||||
addVideoPipeline();
|
||||
inited = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CallSession::addVideoPipeline()
|
||||
{
|
||||
qCDebug(voip) << "Adding Video Pipeline";
|
||||
auto videoconvert = createElement("videoconvertscale", m_pipe);
|
||||
auto tee = createElement("tee", m_pipe);
|
||||
auto device = VideoSources::instance().currentDevice();
|
||||
auto deviceCaps = device->caps[VideoSources::instance().capsIndex()];
|
||||
int width = deviceCaps.width;
|
||||
int height = deviceCaps.height;
|
||||
int framerate = deviceCaps.framerates.back();
|
||||
if (!device) {
|
||||
return false;
|
||||
}
|
||||
auto camera = gst_device_create_element(device->device, nullptr);
|
||||
gst_bin_add_many(GST_BIN(m_pipe), camera, nullptr);
|
||||
|
||||
auto caps =
|
||||
gst_caps_new_simple("video/x-raw", "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, framerate, 1, nullptr);
|
||||
auto camerafilter = createElement("capsfilter", m_pipe);
|
||||
g_object_set(camerafilter, "caps", caps, nullptr);
|
||||
gst_caps_unref(caps);
|
||||
|
||||
gst_element_link(camera, videoconvert);
|
||||
|
||||
if (!gst_element_link_many(videoconvert, camerafilter, nullptr)) {
|
||||
qCWarning(voip) << "Failed to link camera elements";
|
||||
// TODO: Error handling
|
||||
return false;
|
||||
}
|
||||
if (!gst_element_link(camerafilter, tee)) {
|
||||
qCWarning(voip) << "Failed to link camerafilter -> tee";
|
||||
// TODO: Error handling
|
||||
return false;
|
||||
}
|
||||
|
||||
auto queue = createElement("queue", m_pipe);
|
||||
g_object_set(queue, "leaky", true, nullptr);
|
||||
auto vp8enc = createElement("vp8enc", m_pipe);
|
||||
g_object_set(vp8enc, "deadline", 1, nullptr);
|
||||
g_object_set(vp8enc, "error-resilient", 1, nullptr);
|
||||
auto rtpvp8pay = createElement("rtpvp8pay", m_pipe);
|
||||
auto rtpqueue = createElement("queue", m_pipe);
|
||||
auto rtpcapsfilter = createElement("capsfilter", m_pipe);
|
||||
auto rtpcaps = gst_caps_new_simple("application/x-rtp",
|
||||
"media",
|
||||
G_TYPE_STRING,
|
||||
"video",
|
||||
"encoding-name",
|
||||
G_TYPE_STRING,
|
||||
"VP8",
|
||||
"payload",
|
||||
G_TYPE_INT,
|
||||
VP8_PAYLOAD_TYPE,
|
||||
nullptr);
|
||||
g_object_set(rtpcapsfilter, "caps", rtpcaps, nullptr);
|
||||
gst_caps_unref(rtpcaps);
|
||||
|
||||
auto webrtcbin = binGetByName(m_pipe, "webrtcbin");
|
||||
if (!gst_element_link_many(tee, queue, vp8enc, rtpvp8pay, rtpqueue, rtpcapsfilter, webrtcbin, nullptr)) {
|
||||
qCCritical(voip) << "Failed to link rtp video elements";
|
||||
gst_object_unref(webrtcbin);
|
||||
return false;
|
||||
}
|
||||
auto promise = gst_promise_new_with_change_func(setLocalDescription, this, nullptr);
|
||||
g_signal_emit_by_name(webrtcbin, "create-offer", nullptr, promise);
|
||||
|
||||
gst_object_unref(webrtcbin);
|
||||
|
||||
auto newpad = gst_element_request_pad_simple(tee, "src_%u");
|
||||
Q_ASSERT(newpad);
|
||||
|
||||
auto fake = createElement("fakesink", m_pipe);
|
||||
auto selector = createElement("output-selector", m_pipe);
|
||||
auto selectorSink = gst_element_get_static_pad(selector, "sink");
|
||||
auto selectorSrc1 = gst_element_request_pad_simple(selector, "src_%u");
|
||||
gst_pad_link(newpad, selectorSink);
|
||||
auto fakepad = gst_element_get_static_pad(fake, "sink");
|
||||
gst_pad_link(selectorSrc1, fakepad);
|
||||
g_object_set(selector, "active-pad", selectorSrc1, nullptr);
|
||||
|
||||
// gst_pad_add_probe(newpad, GST_PAD_PROBE_TYPE_EVENT_BOTH, pad_cb, stream, nullptr);
|
||||
auto manager = dynamic_cast<CallManager *>(parent());
|
||||
auto participants = manager->callParticipants();
|
||||
auto user = dynamic_cast<NeoChatUser *>(manager->room()->localUser());
|
||||
participants->setHasCamera(user, true);
|
||||
|
||||
connectSingleShot(participants->callParticipantForUser(user), &CallParticipant::initialized, this, [=](QQuickItem *item) {
|
||||
gst_pad_unlink(newpad, fakepad);
|
||||
Q_ASSERT(item);
|
||||
|
||||
auto queue = newVideoSinkChain(m_pipe, item);
|
||||
Q_ASSERT(queue);
|
||||
auto queuepad = gst_element_get_static_pad(queue, "sink");
|
||||
Q_ASSERT(queuepad);
|
||||
auto selectorSrc = gst_element_request_pad_simple(selector, "src_%u");
|
||||
Q_ASSERT(selectorSrc);
|
||||
auto ok = GST_PAD_LINK_SUCCESSFUL(gst_pad_link(selectorSrc, queuepad));
|
||||
Q_ASSERT(ok);
|
||||
g_object_set(selector, "active-pad", selectorSrc, nullptr);
|
||||
gst_object_unref(queuepad);
|
||||
gst_element_set_state(m_pipe, GST_STATE_READY); // TODO experimental
|
||||
gst_element_set_state(m_pipe, GST_STATE_PLAYING); // TODO experimental
|
||||
GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_pipe), GST_DEBUG_GRAPH_SHOW_ALL, "foo");
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
void CallSession::setTurnServers(QStringList servers)
|
||||
{
|
||||
qCDebug(voip) << "Setting Turn Servers";
|
||||
qWarning() << "TURN SERVERS" << servers;
|
||||
m_turnServers = servers;
|
||||
}
|
||||
|
||||
void CallSession::acceptCandidates(const QVector<Candidate> &candidates)
|
||||
{
|
||||
qCDebug(voip) << "Accepting ICE Candidates";
|
||||
auto webrtcbin = binGetByName(m_pipe, "webrtcbin");
|
||||
for (const auto &c : candidates) {
|
||||
qCDebug(voip) << "Remote candidate:" << c.candidate << c.sdpMLineIndex;
|
||||
g_signal_emit_by_name(webrtcbin, "add-ice-candidate", c.sdpMLineIndex, c.candidate.toLatin1().data());
|
||||
}
|
||||
}
|
||||
|
||||
QStringList CallSession::missingPlugins()
|
||||
{
|
||||
GstRegistry *registry = gst_registry_get();
|
||||
static const QVector<QString> videoPlugins = {
|
||||
QLatin1String("compositor"),
|
||||
QLatin1String("opengl"),
|
||||
QLatin1String("qmlgl"),
|
||||
QLatin1String("rtp"),
|
||||
QLatin1String("videoconvertscale"),
|
||||
QLatin1String("vpx"),
|
||||
};
|
||||
static const QVector<QString> audioPlugins = {
|
||||
QStringLiteral("audioconvert"),
|
||||
QStringLiteral("audioresample"),
|
||||
QStringLiteral("autodetect"),
|
||||
QStringLiteral("dtls"),
|
||||
QStringLiteral("nice"),
|
||||
QStringLiteral("opus"),
|
||||
QStringLiteral("playback"),
|
||||
QStringLiteral("rtpmanager"),
|
||||
QStringLiteral("srtp"),
|
||||
QStringLiteral("volume"),
|
||||
QStringLiteral("webrtc"),
|
||||
};
|
||||
QStringList missingPlugins;
|
||||
for (const auto &pluginName : videoPlugins + audioPlugins) {
|
||||
auto plugin = gst_registry_find_plugin(registry, pluginName.toLatin1().data());
|
||||
if (!plugin) {
|
||||
missingPlugins << pluginName;
|
||||
}
|
||||
gst_object_unref(plugin);
|
||||
}
|
||||
return missingPlugins;
|
||||
}
|
||||
|
||||
void CallSession::setMuted(bool muted)
|
||||
{
|
||||
const auto srclevel = binGetByName(m_pipe, "srclevel");
|
||||
g_object_set(srclevel, "mute", muted, nullptr);
|
||||
gst_object_unref(srclevel);
|
||||
Q_EMIT mutedChanged();
|
||||
}
|
||||
|
||||
bool CallSession::muted() const
|
||||
{
|
||||
if (m_state < CallSession::CONNECTING) {
|
||||
return false;
|
||||
}
|
||||
if (!m_pipe) {
|
||||
return false;
|
||||
}
|
||||
const auto srclevel = binGetByName(m_pipe, "srclevel");
|
||||
bool muted;
|
||||
if (!srclevel) {
|
||||
return false;
|
||||
}
|
||||
g_object_get(srclevel, "mute", &muted, nullptr);
|
||||
// gst_object_unref(srclevel); //TODO why does this crash?
|
||||
return muted;
|
||||
}
|
||||
|
||||
CallSession *
|
||||
CallSession::acceptCall(const QString &sdp, const QVector<Candidate> &candidates, const QStringList &turnUris, const QString &userId, QObject *parent)
|
||||
{
|
||||
auto instance = new CallSession(parent);
|
||||
instance->setTurnServers(turnUris);
|
||||
instance->acceptOffer(sdp, candidates, userId);
|
||||
return instance;
|
||||
}
|
||||
|
||||
CallSession *CallSession::startCall(const QStringList &turnUris, QObject *parent)
|
||||
{
|
||||
auto instance = new CallSession(parent);
|
||||
|
||||
instance->setTurnServers(turnUris);
|
||||
instance->createCall();
|
||||
return instance;
|
||||
}
|
||||
|
||||
CallSession::State CallSession::state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void CallSession::setState(CallSession::State state)
|
||||
{
|
||||
qCWarning(voip) << "Setting state" << state;
|
||||
m_state = state;
|
||||
Q_EMIT stateChanged();
|
||||
}
|
||||
|
||||
void CallSession::setMetadata(QJsonObject metadata)
|
||||
{
|
||||
m_metadata = metadata;
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
||||
// SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu>
|
||||
// SPDX-FileCopyrightText: 2021-2022 Tobias Fella <fella@posteo.de>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QMetaType>
|
||||
#include <QObject>
|
||||
#include <QQuickItem>
|
||||
#include <QString>
|
||||
#include <variant>
|
||||
#define GST_USE_UNSTABLE_API
|
||||
#include <gst/webrtc/webrtc.h>
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#define OPUS_PAYLOAD_TYPE 111
|
||||
#define VP8_PAYLOAD_TYPE 96
|
||||
|
||||
class CallDevices;
|
||||
class VideoStream;
|
||||
|
||||
struct Candidate {
|
||||
QString candidate;
|
||||
int sdpMLineIndex;
|
||||
QString sdpMid;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Candidate)
|
||||
Q_DECLARE_METATYPE(QVector<Candidate>)
|
||||
|
||||
class CallSession : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum State {
|
||||
DISCONNECTED,
|
||||
ICEFAILED,
|
||||
INITIATING,
|
||||
INITIATED,
|
||||
OFFERSENT,
|
||||
ANSWERSENT,
|
||||
CONNECTING,
|
||||
CONNECTED,
|
||||
};
|
||||
Q_ENUM(State);
|
||||
|
||||
Q_PROPERTY(CallSession::State state READ state NOTIFY stateChanged)
|
||||
Q_PROPERTY(bool muted READ muted WRITE setMuted NOTIFY mutedChanged)
|
||||
|
||||
// For outgoing calls
|
||||
static CallSession *startCall(const QStringList &turnUris, QObject *parent = nullptr);
|
||||
void acceptAnswer(const QString &sdp, const QVector<Candidate> &candidates, const QString &parent);
|
||||
|
||||
// For incoming calls
|
||||
static CallSession *
|
||||
acceptCall(const QString &sdp, const QVector<Candidate> &candidates, const QStringList &turnUris, const QString &userId, QObject *parent = nullptr);
|
||||
|
||||
void end();
|
||||
|
||||
void renegotiateOffer(const QString &offer, const QString &userId, bool answer);
|
||||
void setTurnServers(QStringList servers);
|
||||
|
||||
static QStringList missingPlugins();
|
||||
|
||||
CallSession::State state() const;
|
||||
|
||||
void toggleCamera();
|
||||
bool muted() const;
|
||||
void setMuted(bool muted);
|
||||
void setMetadata(QJsonObject metadata);
|
||||
void acceptCandidates(const QVector<Candidate> &candidates);
|
||||
|
||||
QMap<QString, QString> msidToUserId;
|
||||
Q_SIGNALS:
|
||||
void stateChanged();
|
||||
void offerCreated(const QString &sdp, const QVector<Candidate> &candidates);
|
||||
|
||||
void answerCreated(const QString &sdp, const QVector<Candidate> &candidates);
|
||||
|
||||
void mutedChanged();
|
||||
void newVideoStream(VideoStream *stream);
|
||||
|
||||
void renegotiate(QString sdp, const QString &type);
|
||||
|
||||
private:
|
||||
CallSession(QObject *parent = nullptr);
|
||||
void acceptOffer(const QString &sdp, const QVector<Candidate> remoteCandidates, const QString &userId);
|
||||
void createCall();
|
||||
|
||||
void setRemoteDescription(GstWebRTCSessionDescription *remote, const QString &userId, GstPromise *promise = nullptr);
|
||||
void startPipeline();
|
||||
void createPipeline();
|
||||
bool addVideoPipeline();
|
||||
|
||||
void setState(CallSession::State state);
|
||||
GstPad *m_activePad;
|
||||
GstElement *m_inputSelector;
|
||||
CallSession::State m_state = CallSession::DISCONNECTED;
|
||||
unsigned int m_busWatchId = 0;
|
||||
QStringList m_turnServers;
|
||||
QVector<Candidate> m_localCandidates;
|
||||
QString m_localSdp;
|
||||
GstElement *m_pipe = nullptr;
|
||||
bool m_isOffering = false;
|
||||
QMap<int, QString> ssrcToMsid;
|
||||
QJsonObject m_metadata;
|
||||
GstPad *m_inactivePad;
|
||||
};
|
||||
@@ -1,165 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
#include "devicemonitor.h"
|
||||
#include "voiplogging.h"
|
||||
#include <QTimer>
|
||||
|
||||
QDebug operator<<(QDebug dbg, const GstStructure *props)
|
||||
{
|
||||
QDebugStateSaver saver(dbg);
|
||||
auto asStr = gst_structure_to_string(props);
|
||||
dbg << asStr;
|
||||
g_free(asStr);
|
||||
return dbg;
|
||||
}
|
||||
|
||||
static gboolean deviceCallback(GstBus *bus, GstMessage *message, gpointer user_data)
|
||||
{
|
||||
Q_UNUSED(bus);
|
||||
auto monitor = static_cast<DeviceMonitor *>(user_data);
|
||||
return monitor->callback(message);
|
||||
}
|
||||
|
||||
DeviceMonitor::DeviceMonitor()
|
||||
: QObject()
|
||||
{
|
||||
QTimer::singleShot(0, this, &DeviceMonitor::init);
|
||||
}
|
||||
|
||||
void DeviceMonitor::init()
|
||||
{
|
||||
if (m_monitor) {
|
||||
return;
|
||||
}
|
||||
m_monitor = gst_device_monitor_new();
|
||||
GstCaps *caps = gst_caps_new_empty_simple("audio/x-raw");
|
||||
gst_device_monitor_add_filter(m_monitor, "Audio/Source", caps);
|
||||
|
||||
gst_caps_unref(caps);
|
||||
caps = gst_caps_new_empty_simple("video/x-raw");
|
||||
gst_device_monitor_add_filter(m_monitor, "Video/Source", caps);
|
||||
gst_caps_unref(caps);
|
||||
|
||||
GstBus *bus = gst_device_monitor_get_bus(m_monitor);
|
||||
gst_bus_add_watch(bus, deviceCallback, this);
|
||||
gst_object_unref(bus);
|
||||
|
||||
if (!gst_device_monitor_start(m_monitor)) {
|
||||
qWarning() << "Failed to start device monitor";
|
||||
}
|
||||
}
|
||||
|
||||
QVector<AudioSource *> DeviceMonitor::audioSources() const
|
||||
{
|
||||
return m_audioSources;
|
||||
}
|
||||
|
||||
QVector<VideoSource *> DeviceMonitor::videoSources() const
|
||||
{
|
||||
return m_videoSources;
|
||||
}
|
||||
|
||||
void DeviceMonitor::handleVideoSource(GstDevice *device)
|
||||
{
|
||||
auto source = new VideoSource();
|
||||
auto title = gst_device_get_display_name(device);
|
||||
source->title = QString(title);
|
||||
g_free(title);
|
||||
source->device = device;
|
||||
|
||||
auto caps = gst_device_get_caps(device);
|
||||
auto size = gst_caps_get_size(caps);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
VideoCap videoCap;
|
||||
GstStructure *cap = gst_caps_get_structure(caps, i);
|
||||
const gchar *name = gst_structure_get_name(cap);
|
||||
if (strcmp(name, "video/x-raw")) {
|
||||
// TODO g_free(name);
|
||||
continue;
|
||||
}
|
||||
// TODO g_free(name);
|
||||
gst_structure_get(cap, "width", G_TYPE_INT, &videoCap.width, "height", G_TYPE_INT, &videoCap.height, nullptr);
|
||||
const auto framerate = gst_structure_get_value(cap, "framerate");
|
||||
if (GST_VALUE_HOLDS_FRACTION(framerate)) {
|
||||
auto numerator = gst_value_get_fraction_numerator(framerate);
|
||||
auto denominator = gst_value_get_fraction_denominator(framerate);
|
||||
videoCap.framerates += (float)numerator / denominator;
|
||||
}
|
||||
// unref cap?
|
||||
source->caps += videoCap;
|
||||
}
|
||||
m_videoSources += source;
|
||||
Q_EMIT videoSourceAdded();
|
||||
}
|
||||
|
||||
void DeviceMonitor::handleAudioSource(GstDevice *device)
|
||||
{
|
||||
auto source = new AudioSource();
|
||||
auto title = gst_device_get_display_name(device);
|
||||
source->title = QString(title);
|
||||
g_free(title);
|
||||
|
||||
GstStructure *props = gst_device_get_properties(device);
|
||||
gboolean isDefault = false;
|
||||
if (gst_structure_has_field(props, "is-default")) {
|
||||
gst_structure_get_boolean(props, "is-default", &isDefault);
|
||||
}
|
||||
gst_structure_free(props);
|
||||
source->isDefault = isDefault;
|
||||
|
||||
source->device = device;
|
||||
m_audioSources += source;
|
||||
Q_EMIT audioSourceAdded();
|
||||
}
|
||||
|
||||
bool DeviceMonitor::callback(GstMessage *message)
|
||||
{
|
||||
GstDevice *device;
|
||||
switch (GST_MESSAGE_TYPE(message)) {
|
||||
case GST_MESSAGE_DEVICE_ADDED: {
|
||||
gst_message_parse_device_added(message, &device);
|
||||
auto name = gst_device_get_display_name(device);
|
||||
auto props = gst_device_get_properties(device);
|
||||
qCDebug(voip) << name << props;
|
||||
gst_structure_free(props);
|
||||
if (gst_device_has_classes(device, "Video/Source")) {
|
||||
handleVideoSource(device);
|
||||
} else if (gst_device_has_classes(device, "Audio/Source")) {
|
||||
handleAudioSource(device);
|
||||
}
|
||||
g_free(name);
|
||||
gst_object_unref(device);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_DEVICE_REMOVED: {
|
||||
gst_message_parse_device_removed(message, &device);
|
||||
auto name = gst_device_get_display_name(device);
|
||||
auto props = gst_device_get_properties(device);
|
||||
qCDebug(voip) << name << props;
|
||||
if (gst_device_has_classes(device, "Video/Source")) {
|
||||
m_videoSources.erase(std::remove_if(m_videoSources.begin(),
|
||||
m_videoSources.end(),
|
||||
[name](auto d) {
|
||||
return d->title == QString(name);
|
||||
}),
|
||||
m_videoSources.end());
|
||||
Q_EMIT videoSourceRemoved();
|
||||
} else if (gst_device_has_classes(device, "Audio/Source")) {
|
||||
m_audioSources.erase(std::remove_if(m_audioSources.begin(),
|
||||
m_audioSources.end(),
|
||||
[name](auto d) {
|
||||
return d->title == QString(name);
|
||||
}),
|
||||
m_audioSources.end());
|
||||
Q_EMIT audioSourceRemoved();
|
||||
}
|
||||
g_free(name);
|
||||
gst_object_unref(device);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QVector>
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
struct AudioSource {
|
||||
QString title;
|
||||
GstDevice *device;
|
||||
bool isDefault;
|
||||
};
|
||||
struct VideoCap {
|
||||
int width;
|
||||
int height;
|
||||
QVector<float> framerates;
|
||||
};
|
||||
|
||||
struct VideoSource {
|
||||
QString title;
|
||||
GstDevice *device;
|
||||
QVector<VideoCap> caps;
|
||||
};
|
||||
|
||||
class DeviceMonitor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static DeviceMonitor &instance()
|
||||
{
|
||||
static DeviceMonitor _instance;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
QVector<AudioSource *> audioSources() const;
|
||||
QVector<VideoSource *> videoSources() const;
|
||||
bool callback(GstMessage *message);
|
||||
void init();
|
||||
|
||||
Q_SIGNALS:
|
||||
void videoSourceAdded();
|
||||
void audioSourceAdded();
|
||||
|
||||
void videoSourceRemoved();
|
||||
void audioSourceRemoved();
|
||||
|
||||
private:
|
||||
DeviceMonitor();
|
||||
GstDeviceMonitor *m_monitor = nullptr;
|
||||
QVector<AudioSource *> m_audioSources;
|
||||
QVector<VideoSource *> m_videoSources;
|
||||
void handleVideoSource(GstDevice *device);
|
||||
void handleAudioSource(GstDevice *device);
|
||||
};
|
||||
@@ -1,142 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
#include "videosources.h"
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
// #include "pipelinemanager.h"
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
|
||||
#include "devicemonitor.h"
|
||||
#include "neochatconfig.h"
|
||||
|
||||
int VideoSources::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return DeviceMonitor::instance().videoSources().size();
|
||||
}
|
||||
|
||||
QVariant VideoSources::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() >= DeviceMonitor::instance().videoSources().size()) {
|
||||
return QVariant(QStringLiteral("DEADBEEF"));
|
||||
}
|
||||
if (role == TitleRole) {
|
||||
return DeviceMonitor::instance().videoSources()[index.row()]->title;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> VideoSources::roleNames() const
|
||||
{
|
||||
return {
|
||||
{TitleRole, "title"},
|
||||
};
|
||||
}
|
||||
|
||||
VideoSources::VideoSources()
|
||||
: QAbstractListModel()
|
||||
{
|
||||
connect(&DeviceMonitor::instance(), &DeviceMonitor::videoSourceAdded, this, [this]() {
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
Q_EMIT currentIndexChanged();
|
||||
});
|
||||
connect(&DeviceMonitor::instance(), &DeviceMonitor::videoSourceRemoved, this, [this]() {
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
Q_EMIT currentIndexChanged();
|
||||
});
|
||||
}
|
||||
|
||||
void VideoSources::foo(int index)
|
||||
{
|
||||
auto device = DeviceMonitor::instance().videoSources()[index]->device;
|
||||
|
||||
auto bin = gst_bin_new(nullptr);
|
||||
|
||||
GstElement *videoconvert = gst_element_factory_make("videoconvert", nullptr);
|
||||
// GstElement *videorate = gst_element_factory_make("videorate", nullptr);
|
||||
|
||||
GstElement *filter = gst_element_factory_make("capsfilter", nullptr);
|
||||
GstCaps *caps = gst_caps_new_simple("video/x-raw", "width", G_TYPE_INT, 1920, "height", G_TYPE_INT, 1080, "framerate", GST_TYPE_FRACTION, 5, 1, nullptr);
|
||||
g_object_set(filter, "caps", caps, nullptr);
|
||||
gst_caps_unref(caps);
|
||||
GstElement *deviceElement = gst_device_create_element(device, nullptr);
|
||||
|
||||
gst_bin_add_many(GST_BIN(bin), deviceElement, videoconvert, filter, nullptr);
|
||||
gst_element_link_many(deviceElement, videoconvert, filter, nullptr);
|
||||
|
||||
// GstPad *pad = gst_element_get_static_pad(filter, "src");
|
||||
GstPad *pad = gst_element_get_static_pad(filter, "src");
|
||||
auto ghostpad = gst_ghost_pad_new("src", pad);
|
||||
gst_element_add_pad(bin, ghostpad);
|
||||
gst_object_unref(pad);
|
||||
// PipelineManager::instance().add(bin);
|
||||
}
|
||||
|
||||
const VideoSource *VideoSources::currentDevice() const
|
||||
{
|
||||
const auto config = NeoChatConfig::self();
|
||||
const QString name = config->camera();
|
||||
for (const auto &videoSource : DeviceMonitor::instance().videoSources()) {
|
||||
if (videoSource->title == name) {
|
||||
qDebug() << "WebRTC: camera:" << name;
|
||||
return videoSource;
|
||||
}
|
||||
}
|
||||
if (DeviceMonitor::instance().videoSources().length() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return DeviceMonitor::instance().videoSources()[0];
|
||||
}
|
||||
|
||||
void VideoSources::setCurrentIndex(int index)
|
||||
{
|
||||
if (DeviceMonitor::instance().videoSources().size() == 0) {
|
||||
return;
|
||||
}
|
||||
NeoChatConfig::setCamera(DeviceMonitor::instance().videoSources()[index]->title);
|
||||
NeoChatConfig::self()->save();
|
||||
|
||||
setCapsIndex(0);
|
||||
}
|
||||
|
||||
int VideoSources::currentIndex() const
|
||||
{
|
||||
const auto config = NeoChatConfig::self();
|
||||
const QString name = config->camera();
|
||||
for (auto i = 0; i < DeviceMonitor::instance().videoSources().size(); i++) {
|
||||
if (DeviceMonitor::instance().videoSources()[i]->title == name) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QStringList VideoSources::caps(int index) const
|
||||
{
|
||||
if (index >= DeviceMonitor::instance().videoSources().size()) {
|
||||
return QStringList();
|
||||
}
|
||||
const auto &caps = DeviceMonitor::instance().videoSources()[index]->caps;
|
||||
QStringList strings;
|
||||
for (const auto &cap : caps) {
|
||||
strings += QStringLiteral("%1x%2, %3 FPS").arg(cap.width).arg(cap.height).arg(cap.framerates.back());
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
|
||||
void VideoSources::setCapsIndex(int index)
|
||||
{
|
||||
NeoChatConfig::self()->setCameraCaps(index);
|
||||
NeoChatConfig::self()->save();
|
||||
Q_EMIT capsIndexChanged();
|
||||
}
|
||||
|
||||
int VideoSources::capsIndex() const
|
||||
{
|
||||
return NeoChatConfig::self()->cameraCaps();
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QAbstractListModel>
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "devicemonitor.h"
|
||||
|
||||
class VideoSources : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
|
||||
Q_PROPERTY(int capsIndex READ capsIndex WRITE setCapsIndex NOTIFY capsIndexChanged)
|
||||
public:
|
||||
enum Roles {
|
||||
TitleRole = Qt::UserRole + 1,
|
||||
DeviceRole,
|
||||
};
|
||||
|
||||
static VideoSources &instance()
|
||||
{
|
||||
static VideoSources _instance;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE void foo(int index);
|
||||
|
||||
const VideoSource *currentDevice() const;
|
||||
|
||||
void setCurrentIndex(int index);
|
||||
int currentIndex() const;
|
||||
|
||||
void setCapsIndex(int index);
|
||||
int capsIndex() const;
|
||||
|
||||
Q_INVOKABLE QStringList caps(int index) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void currentIndexChanged();
|
||||
void capsIndexChanged();
|
||||
|
||||
private:
|
||||
VideoSources();
|
||||
};
|
||||
@@ -736,12 +736,3 @@ QVariantList Controller::getSupportedRoomVersions(Quotient::Connection *connecti
|
||||
|
||||
return supportedRoomVersions;
|
||||
}
|
||||
|
||||
bool Controller::callsSupported() const
|
||||
{
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -100,7 +100,6 @@ class Controller : public QObject
|
||||
* This is the only way to gate NeoChat features in flatpaks in QML.
|
||||
*/
|
||||
Q_PROPERTY(bool isFlatpak READ isFlatpak CONSTANT)
|
||||
Q_PROPERTY(bool callsSupported READ callsSupported CONSTANT)
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -198,7 +197,6 @@ public:
|
||||
int quotientMinorVersion() const;
|
||||
|
||||
bool isFlatpak() const;
|
||||
bool callsSupported() const;
|
||||
|
||||
/**
|
||||
* @brief Return a string for the input timestamp.
|
||||
|
||||
39
src/main.cpp
39
src/main.cpp
@@ -57,6 +57,7 @@
|
||||
#include "models/emoticonfiltermodel.h"
|
||||
#include "models/imagepacksmodel.h"
|
||||
#include "models/keywordnotificationrulemodel.h"
|
||||
#include "models/livelocationsmodel.h"
|
||||
#include "models/messageeventmodel.h"
|
||||
#include "models/messagefiltermodel.h"
|
||||
#include "models/publicroomlistmodel.h"
|
||||
@@ -86,8 +87,6 @@
|
||||
#ifdef QUOTIENT_07
|
||||
#include <keyverificationsession.h>
|
||||
#endif
|
||||
#include <room.h>
|
||||
|
||||
#ifdef HAVE_COLORSCHEME
|
||||
#include "colorschemer.h"
|
||||
#endif
|
||||
@@ -95,14 +94,6 @@
|
||||
#include "models/statemodel.h"
|
||||
#include "neochatuser.h"
|
||||
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
#include "call/audiosources.h"
|
||||
#include "call/callmanager.h"
|
||||
#include "call/callparticipant.h"
|
||||
#include "call/videosources.h"
|
||||
#include "models/callparticipantsmodel.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_RUNNER
|
||||
#include "runner.h"
|
||||
#include <QDBusConnection>
|
||||
@@ -193,22 +184,6 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
QStringLiteral("https://github.com/quotient-im/libquotient"),
|
||||
KAboutLicense::LGPL_V2_1);
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
guint major, minor, micro, nano;
|
||||
gst_version(&major, &minor, µ, &nano);
|
||||
about.addComponent(QStringLiteral("GStreamer"),
|
||||
i18nc("Description of GStreamer", "Open Source Multimedia Framework"),
|
||||
i18nc("<version number> (built against <possibly different version number>)",
|
||||
"%1.%2.%3.%4 (built against %5.%6.%7.%8)",
|
||||
major,
|
||||
minor,
|
||||
micro,
|
||||
nano,
|
||||
GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
GST_VERSION_MICRO,
|
||||
GST_VERSION_NANO));
|
||||
#endif
|
||||
|
||||
KAboutData::setApplicationData(about);
|
||||
QGuiApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("org.kde.neochat")));
|
||||
@@ -273,6 +248,7 @@ int main(int argc, char *argv[])
|
||||
qmlRegisterType<StateModel>("org.kde.neochat", 1, 0, "StateModel");
|
||||
qmlRegisterType<StateFilterModel>("org.kde.neochat", 1, 0, "StateFilterModel");
|
||||
qmlRegisterType<SearchModel>("org.kde.neochat", 1, 0, "SearchModel");
|
||||
qmlRegisterType<LiveLocationsModel>("org.kde.neochat", 1, 0, "LiveLocationsModel");
|
||||
#ifdef QUOTIENT_07
|
||||
qmlRegisterType<PollHandler>("org.kde.neochat", 1, 0, "PollHandler");
|
||||
#endif
|
||||
@@ -289,10 +265,6 @@ int main(int argc, char *argv[])
|
||||
qmlRegisterUncreatableType<NeoChatUser>("org.kde.neochat", 1, 0, "NeoChatUser", {});
|
||||
qmlRegisterUncreatableType<NeoChatRoom>("org.kde.neochat", 1, 0, "NeoChatRoom", {});
|
||||
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
qmlRegisterUncreatableType<CallParticipantsModel>("org.kde.neochat", 1, 0, "CallParticipantsModel", "Get through CallManager");
|
||||
qmlRegisterUncreatableType<CallParticipant>("org.kde.neochat", 1, 0, "CallParticipant", "Get through model");
|
||||
#endif
|
||||
qRegisterMetaType<User *>("User*");
|
||||
qRegisterMetaType<User *>("const User*");
|
||||
qRegisterMetaType<User *>("const Quotient::User*");
|
||||
@@ -309,13 +281,6 @@ int main(int argc, char *argv[])
|
||||
qmlRegisterUncreatableType<KeyVerificationSession>("org.kde.neochat", 1, 0, "KeyVerificationSession", {});
|
||||
qRegisterMetaType<QVector<EmojiEntry>>("QVector<EmojiEntry>");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "AudioSources", &AudioSources::instance());
|
||||
qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "VideoSources", &VideoSources::instance());
|
||||
qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "CallManager", &CallManager::instance());
|
||||
qmlRegisterUncreatableType<CallSession>("org.kde.neochat", 1, 0, "CallSession", "ENUM");
|
||||
#endif
|
||||
qmlRegisterSingletonType("org.kde.neochat", 1, 0, "About", [](QQmlEngine *engine, QJSEngine *) -> QJSValue {
|
||||
return engine->toScriptValue(KAboutData::applicationData());
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "callparticipantsmodel.h"
|
||||
|
||||
QVariant CallParticipantsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role == ObjectRole) {
|
||||
return QVariant::fromValue(m_callParticipants[index.row()]);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
int CallParticipantsModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return m_callParticipants.size();
|
||||
}
|
||||
|
||||
void CallParticipantsModel::clear()
|
||||
{
|
||||
beginRemoveRows(QModelIndex(), 0, m_callParticipants.size() - 1);
|
||||
m_callParticipants.clear();
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
CallParticipant *CallParticipantsModel::callParticipantForUser(NeoChatUser *user)
|
||||
{
|
||||
for (const auto &callParticipant : m_callParticipants) {
|
||||
if (callParticipant->m_user == user) {
|
||||
return callParticipant;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> CallParticipantsModel::roleNames() const
|
||||
{
|
||||
return {
|
||||
{WidthRole, "width"},
|
||||
{HeightRole, "height"},
|
||||
{PadRole, "pad"},
|
||||
{ObjectRole, "object"},
|
||||
};
|
||||
}
|
||||
|
||||
void CallParticipantsModel::addParticipant(CallParticipant *callParticipant)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_callParticipants.size(), m_callParticipants.size());
|
||||
m_callParticipants += callParticipant;
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void CallParticipantsModel::setHasCamera(NeoChatUser *user, bool hasCamera)
|
||||
{
|
||||
callParticipantForUser(user)->m_hasCamera = hasCamera;
|
||||
Q_EMIT callParticipantForUser(user)->hasCameraChanged();
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QVector>
|
||||
|
||||
#include "call/callparticipant.h"
|
||||
#include "neochatuser.h"
|
||||
|
||||
class CallParticipantsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
WidthRole,
|
||||
HeightRole,
|
||||
PadRole,
|
||||
ObjectRole,
|
||||
};
|
||||
Q_ENUM(Roles);
|
||||
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||
;
|
||||
|
||||
void addParticipant(CallParticipant *callParticipant);
|
||||
CallParticipant *callParticipantForUser(NeoChatUser *user);
|
||||
|
||||
void setHasCamera(NeoChatUser *user, bool hasCamera);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
QVector<CallParticipant *> m_callParticipants;
|
||||
};
|
||||
171
src/models/livelocationsmodel.cpp
Normal file
171
src/models/livelocationsmodel.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-FileCopyrightText: 2023 Volker Krause <vkrause@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "livelocationsmodel.h"
|
||||
|
||||
#include <Quotient/events/roommessageevent.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
bool operator<(const LiveLocationData &lhs, const LiveLocationData &rhs)
|
||||
{
|
||||
return lhs.eventId < rhs.eventId;
|
||||
}
|
||||
|
||||
LiveLocationsModel::LiveLocationsModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
connect(
|
||||
this,
|
||||
&LiveLocationsModel::roomChanged,
|
||||
this,
|
||||
[this]() {
|
||||
for (const auto &event : m_room->messageEvents()) {
|
||||
addEvent(event.get());
|
||||
}
|
||||
connect(m_room, &NeoChatRoom::aboutToAddHistoricalMessages, this, [this](const auto &events) {
|
||||
for (const auto &event : events) {
|
||||
addEvent(event.get());
|
||||
}
|
||||
});
|
||||
connect(m_room, &NeoChatRoom::aboutToAddNewMessages, this, [this](const auto &events) {
|
||||
for (const auto &event : events) {
|
||||
addEvent(event.get());
|
||||
}
|
||||
});
|
||||
},
|
||||
Qt::QueuedConnection); // deferred so we are sure the eventId filter is set
|
||||
|
||||
connect(this, &LiveLocationsModel::dataChanged, this, &LiveLocationsModel::boundingBoxChanged);
|
||||
connect(this, &LiveLocationsModel::rowsInserted, this, &LiveLocationsModel::boundingBoxChanged);
|
||||
}
|
||||
|
||||
int LiveLocationsModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return m_locations.size();
|
||||
}
|
||||
|
||||
QVariant LiveLocationsModel::data(const QModelIndex &index, int roleName) const
|
||||
{
|
||||
if (!checkIndex(index)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto &data = m_locations.at(index.row());
|
||||
switch (roleName) {
|
||||
case LatitudeRole: {
|
||||
const auto geoUri = data.beacon["org.matrix.msc3488.location"_ls].toObject()["uri"_ls].toString();
|
||||
if (geoUri.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
const auto latitude = geoUri.split(u';')[0].split(u':')[1].split(u',')[0];
|
||||
return latitude.toFloat();
|
||||
}
|
||||
case LongitudeRole: {
|
||||
const auto geoUri = data.beacon["org.matrix.msc3488.location"_ls].toObject()["uri"_ls].toString();
|
||||
if (geoUri.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
const auto longitude = geoUri.split(u';')[0].split(u':')[1].split(u',')[1];
|
||||
return longitude.toFloat();
|
||||
}
|
||||
case AssetRole:
|
||||
return data.beaconInfo["org.matrix.msc3488.asset"_ls].toObject()["type"].toString();
|
||||
case AuthorRole:
|
||||
return m_room->getUser(data.senderId);
|
||||
case IsLiveRole: {
|
||||
if (!data.beaconInfo["live"_ls].toBool()) {
|
||||
return false;
|
||||
}
|
||||
// TODO Qt6: port to toInteger(), timestamps are in ms since epoch, ie. 64 bit values
|
||||
const auto lastTs = std::max(data.beaconInfo.value("org.matrix.msc3488.ts"_ls).toDouble(), data.beacon.value("org.matrix.msc3488.ts"_ls).toDouble());
|
||||
const auto timeout = data.beaconInfo.value("timeout"_ls).toDouble(600000);
|
||||
return lastTs + timeout >= QDateTime::currentDateTime().toMSecsSinceEpoch();
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> LiveLocationsModel::roleNames() const
|
||||
{
|
||||
auto r = QAbstractListModel::roleNames();
|
||||
r.insert(LatitudeRole, "latitude");
|
||||
r.insert(LongitudeRole, "longitude");
|
||||
r.insert(AssetRole, "asset");
|
||||
r.insert(AuthorRole, "author");
|
||||
r.insert(IsLiveRole, "isLive");
|
||||
return r;
|
||||
}
|
||||
|
||||
QRectF LiveLocationsModel::boundingBox() const
|
||||
{
|
||||
QRectF bbox(QPointF(180.0, 90.0), QPointF(-180.0, -90.0));
|
||||
for (auto i = 0; i < rowCount(); ++i) {
|
||||
const auto lat = data(index(i, 0), LatitudeRole).toDouble();
|
||||
const auto lon = data(index(i, 0), LongitudeRole).toDouble();
|
||||
|
||||
bbox.setLeft(std::min(bbox.left(), lon));
|
||||
bbox.setRight(std::max(bbox.right(), lon));
|
||||
bbox.setTop(std::min(bbox.top(), lat));
|
||||
bbox.setBottom(std::max(bbox.bottom(), lat));
|
||||
}
|
||||
return bbox;
|
||||
}
|
||||
|
||||
void LiveLocationsModel::addEvent(const Quotient::RoomEvent *event)
|
||||
{
|
||||
if (event->isStateEvent() && event->matrixType() == "org.matrix.msc3672.beacon_info") {
|
||||
LiveLocationData data;
|
||||
data.senderId = event->senderId();
|
||||
data.beaconInfo = event->contentJson();
|
||||
if (event->contentJson()["live"_ls].toBool()) {
|
||||
data.eventId = event->id();
|
||||
} else {
|
||||
data.eventId = event->fullJson()["replaces_state"_ls].toString();
|
||||
}
|
||||
updateLocationData(std::move(data));
|
||||
}
|
||||
if (event->matrixType() == "org.matrix.msc3672.beacon"_ls) {
|
||||
LiveLocationData data;
|
||||
data.eventId = event->contentJson()["m.relates_to"_ls].toObject()["event_id"_ls].toString();
|
||||
data.senderId = event->senderId();
|
||||
data.beacon = event->contentJson();
|
||||
updateLocationData(std::move(data));
|
||||
}
|
||||
}
|
||||
|
||||
void LiveLocationsModel::updateLocationData(LiveLocationData &&data)
|
||||
{
|
||||
if (!m_eventId.isEmpty() && data.eventId != m_eventId) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = std::lower_bound(m_locations.begin(), m_locations.end(), data);
|
||||
if (it == m_locations.end() || it->eventId != data.eventId) {
|
||||
const auto row = std::distance(m_locations.begin(), it);
|
||||
beginInsertRows({}, row, row);
|
||||
m_locations.insert(it, std::move(data));
|
||||
endInsertRows();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto idx = index(std::distance(m_locations.begin(), it), 0);
|
||||
|
||||
// TODO Qt6: port to toInteger(), timestamps are in ms since epoch, ie. 64 bit values
|
||||
if (it->beacon.isEmpty() || it->beacon.value("org.matrix.msc3488.ts"_ls).toDouble() < data.beacon.value("org.matrix.msc3488.ts"_ls).toDouble()) {
|
||||
it->beacon = std::move(data.beacon);
|
||||
}
|
||||
if (it->beaconInfo.isEmpty()
|
||||
|| it->beaconInfo.value("org.matrix.msc3488.ts"_ls).toDouble() < data.beaconInfo.value("org.matrix.msc3488.ts"_ls).toDouble()) {
|
||||
it->beaconInfo = std::move(data.beaconInfo);
|
||||
}
|
||||
|
||||
Q_EMIT dataChanged(idx, idx);
|
||||
}
|
||||
74
src/models/livelocationsmodel.h
Normal file
74
src/models/livelocationsmodel.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-FileCopyrightText: 2023 Volker Krause <vkrause@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "neochatroom.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QPointer>
|
||||
#include <QRectF>
|
||||
|
||||
namespace Quotient
|
||||
{
|
||||
class RoomMessageEvent;
|
||||
}
|
||||
|
||||
struct LiveLocationData {
|
||||
QString eventId;
|
||||
QString senderId;
|
||||
QJsonObject beaconInfo;
|
||||
QJsonObject beacon;
|
||||
};
|
||||
bool operator<(const LiveLocationData &lhs, const LiveLocationData &rhs);
|
||||
|
||||
/** Accumulates live location beacon events in a given room
|
||||
* and provides the last known state for one or more live location beacons.
|
||||
*/
|
||||
class LiveLocationsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(NeoChatRoom *room MEMBER m_room NOTIFY roomChanged)
|
||||
/** The event id of the beacon start event, ie. the one all suspequent
|
||||
* events use to relate to the same beacon.
|
||||
* If this is set only this specific beacon will be coverd by this model,
|
||||
* if it is empty, all beacons in the room will be covered.
|
||||
*/
|
||||
Q_PROPERTY(QString eventId MEMBER m_eventId NOTIFY eventIdChanged)
|
||||
|
||||
/** Bounding box of all live location beacons covered by this model. */
|
||||
Q_PROPERTY(QRectF boundingBox READ boundingBox NOTIFY boundingBoxChanged)
|
||||
|
||||
public:
|
||||
explicit LiveLocationsModel(QObject *parent = nullptr);
|
||||
|
||||
enum Roles {
|
||||
LatitudeRole, /**< Latest latitude of a live locaction beacon. */
|
||||
LongitudeRole, /**< Latest longitude of a live locaction beacon. */
|
||||
AssetRole, /**< Type of location event, e.g. self pin of the user location. */
|
||||
AuthorRole, /**< The author of the event. */
|
||||
IsLiveRole, /**< Boolean that indicates whether a live location beacon is still live. */
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
int rowCount(const QModelIndex &parent = {}) const override;
|
||||
QVariant data(const QModelIndex &index, int roleName) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
QRectF boundingBox() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void roomChanged();
|
||||
void eventIdChanged();
|
||||
void boundingBoxChanged();
|
||||
|
||||
private:
|
||||
void addEvent(const Quotient::RoomEvent *event);
|
||||
void updateLocationData(LiveLocationData &&data);
|
||||
|
||||
QPointer<NeoChatRoom> m_room;
|
||||
QString m_eventId;
|
||||
|
||||
QList<LiveLocationData> m_locations;
|
||||
};
|
||||
@@ -521,13 +521,13 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
||||
|
||||
return DelegateType::Message;
|
||||
}
|
||||
if (evt.matrixType() == "m.call.invite") {
|
||||
return DelegateType::CallInvite;
|
||||
}
|
||||
if (is<const StickerEvent>(evt)) {
|
||||
return DelegateType::Sticker;
|
||||
}
|
||||
if (evt.isStateEvent()) {
|
||||
if (evt.matrixType() == "org.matrix.msc3672.beacon_info"_ls) {
|
||||
return DelegateType::LiveLocation;
|
||||
}
|
||||
return DelegateType::State;
|
||||
}
|
||||
if (is<const EncryptedEvent>(evt)) {
|
||||
@@ -638,6 +638,11 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
||||
return EventStatus::Hidden;
|
||||
}
|
||||
|
||||
// hide ending live location beacons
|
||||
if (evt.isStateEvent() && evt.matrixType() == "org.matrix.msc3672.beacon_info"_ls && !evt.contentJson()["live"_ls].toBool()) {
|
||||
return EventStatus::Hidden;
|
||||
}
|
||||
|
||||
return EventStatus::Normal;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
ReadMarker, /**< The local user read marker. */
|
||||
Poll, /**< The initial event for a poll. */
|
||||
Location, /**< A location event. */
|
||||
CallInvite, /**< An invitation to a call. */
|
||||
LiveLocation, /**< The initial event of a shared live location (i.e., the place where this is supposed to be shown in the timeline). */
|
||||
Other, /**< Anything that cannot be classified as another type. */
|
||||
};
|
||||
Q_ENUM(DelegateType);
|
||||
|
||||
@@ -234,23 +234,12 @@ void RoomListModel::handleNotifications()
|
||||
} else {
|
||||
avatar_image = room->avatar(128);
|
||||
}
|
||||
if (notification["event"]["type"].toString() == QStringLiteral("m.call.invite")) {
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
NotificationsManager::instance().postCallInviteNotification(
|
||||
dynamic_cast<NeoChatRoom *>(room),
|
||||
room->displayName(),
|
||||
sender->displayname(room),
|
||||
avatar_image,
|
||||
notification["event"]["content"]["offer"]["sdp"].toString().contains(QStringLiteral("video")));
|
||||
#endif
|
||||
} else {
|
||||
NotificationsManager::instance().postNotification(dynamic_cast<NeoChatRoom *>(room),
|
||||
sender->displayname(room),
|
||||
notification["event"].toObject()["content"].toObject()["body"].toString(),
|
||||
avatar_image,
|
||||
notification["event"].toObject()["event_id"].toString(),
|
||||
true);
|
||||
}
|
||||
NotificationsManager::instance().postNotification(dynamic_cast<NeoChatRoom *>(room),
|
||||
sender->displayname(room),
|
||||
notification["event"].toObject()["content"].toObject()["body"].toString(),
|
||||
avatar_image,
|
||||
notification["event"].toObject()["event_id"].toString(),
|
||||
true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
PowerLevelRole, /**< The user's power level in the current room. */
|
||||
PowerLevelStringRole, /**< The name of the user's power level in the current room. */
|
||||
};
|
||||
Q_ENUM(EventRoles)
|
||||
|
||||
UserListModel(QObject *parent = nullptr);
|
||||
|
||||
|
||||
@@ -54,12 +54,12 @@ QVariant AccountRegistry::data(const QModelIndex &index, int role) const
|
||||
const auto account = m_accounts[index.row()];
|
||||
|
||||
switch (role) {
|
||||
case ConnectionRole:
|
||||
return QVariant::fromValue(account);
|
||||
case UserIdRole:
|
||||
return QVariant::fromValue(account->userId());
|
||||
default:
|
||||
return {};
|
||||
case ConnectionRole:
|
||||
return QVariant::fromValue(account);
|
||||
case UserIdRole:
|
||||
return QVariant::fromValue(account->userId());
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
||||
return {};
|
||||
|
||||
@@ -147,23 +147,5 @@
|
||||
<default></default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="Voip">
|
||||
<entry name="Microphone" type="string">
|
||||
<label>Name of the microphone</label>
|
||||
</entry>
|
||||
<entry name="Camera" type="string">
|
||||
<label>Name of the camera</label>
|
||||
</entry>
|
||||
<entry name="CameraCaps" type="int">
|
||||
<label>Index of the camera caps</label>
|
||||
</entry>
|
||||
<entry name="ScreenShareFrameRate" type="int">
|
||||
<label>Frame rate of the screenshare</label>
|
||||
</entry>
|
||||
<entry name="Ringtone" type="String">
|
||||
<label>Ringtone</label>
|
||||
<default>/usr/share/sounds/plasma-mobile/stereo/ringtones/Spatial.oga</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
||||
|
||||
@@ -42,9 +42,6 @@
|
||||
#endif
|
||||
#include <qt_connection_util.h>
|
||||
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
#include "call/callmanager.h"
|
||||
#endif
|
||||
#include "controller.h"
|
||||
#include "events/joinrulesevent.h"
|
||||
#include "neochatconfig.h"
|
||||
@@ -125,13 +122,6 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS
|
||||
Q_EMIT canEncryptRoomChanged();
|
||||
});
|
||||
connect(connection, &Connection::capabilitiesLoaded, this, &NeoChatRoom::maxRoomVersionChanged);
|
||||
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
connect(this, &Room::callEvent, this, [=](Room *room, const RoomEvent *event) {
|
||||
CallManager::instance().handleCallEvent(static_cast<NeoChatRoom *>(room), event);
|
||||
});
|
||||
#endif
|
||||
|
||||
connect(this, &Room::changed, this, [this]() {
|
||||
Q_EMIT defaultUrlPreviewStateChanged();
|
||||
});
|
||||
@@ -1687,6 +1677,7 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state)
|
||||
|
||||
m_currentPushNotificationState = state;
|
||||
Q_EMIT pushNotificationStateChanged(m_currentPushNotificationState);
|
||||
|
||||
}
|
||||
|
||||
void NeoChatRoom::updatePushNotificationState(QString type)
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
#include <csapi/pushrules.h>
|
||||
#include <jobs/basejob.h>
|
||||
#include <user.h>
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
#include "call/callmanager.h"
|
||||
#endif
|
||||
|
||||
#include "controller.h"
|
||||
#include "neochatconfig.h"
|
||||
@@ -609,35 +606,3 @@ QVector<QVariant> NotificationsManager::toActions(PushNotificationAction::Action
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
#ifdef GSTREAMER_AVAILABLE
|
||||
void NotificationsManager::postCallInviteNotification(NeoChatRoom *room, const QString &roomName, const QString &sender, const QImage &icon, bool video)
|
||||
{
|
||||
QPixmap img;
|
||||
img.convertFromImage(icon);
|
||||
KNotification *notification = new KNotification("message");
|
||||
|
||||
if (sender == roomName) {
|
||||
notification->setTitle(sender);
|
||||
} else {
|
||||
notification->setTitle(i18n("%1 (%2)", sender, roomName));
|
||||
}
|
||||
|
||||
notification->setText(video ? i18n("%1 is inviting you to a video call", sender) : i18n("%1 is inviting you to a voice call", sender));
|
||||
notification->setPixmap(img);
|
||||
notification->setDefaultAction(i18n("Open NeoChat in this room"));
|
||||
connect(notification, &KNotification::defaultActivated, this, [=]() {
|
||||
RoomManager::instance().enterRoom(room);
|
||||
WindowController::instance().showAndRaiseWindow(notification->xdgActivationToken());
|
||||
});
|
||||
notification->setActions({i18n("Accept"), i18n("Decline")});
|
||||
connect(notification, &KNotification::action1Activated, this, [=]() {
|
||||
CallManager::instance().acceptCall();
|
||||
});
|
||||
connect(notification, &KNotification::action2Activated, this, [=]() {
|
||||
CallManager::instance().hangupCall();
|
||||
});
|
||||
notification->sendEvent();
|
||||
m_notifications.insert(room->id(), notification);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -156,7 +156,6 @@ public:
|
||||
* @brief Display a native notification for an invite.
|
||||
*/
|
||||
void postInviteNotification(NeoChatRoom *room, const QString &title, const QString &sender, const QImage &icon);
|
||||
void postCallInviteNotification(NeoChatRoom *room, const QString &roomName, const QString &sender, const QImage &icon, bool video);
|
||||
|
||||
/**
|
||||
* @brief Clear an existing invite notification for the given room.
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2022 Carson Black <uhhadd@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.7 as QQC2
|
||||
import QtQuick.Layouts 1.1
|
||||
import org.kde.kirigami 2.13 as Kirigami
|
||||
|
||||
QQC2.AbstractButton {
|
||||
id: control
|
||||
|
||||
property int temprament: CallPageButton.Neutral
|
||||
property bool shimmering: false
|
||||
|
||||
enum Temprament {
|
||||
Neutral,
|
||||
Constructive,
|
||||
Destructive
|
||||
}
|
||||
|
||||
padding: Kirigami.Units.largeSpacing
|
||||
contentItem: ColumnLayout {
|
||||
QQC2.Control {
|
||||
padding: Kirigami.Units.gridUnit
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Button
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
contentItem: Kirigami.Icon {
|
||||
implicitHeight: Kirigami.Units.iconSizes.medium
|
||||
implicitWidth: Kirigami.Units.iconSizes.medium
|
||||
source: control.icon.name
|
||||
}
|
||||
background: Rectangle {
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Button
|
||||
|
||||
ShimmerGradient {
|
||||
id: shimmerGradient
|
||||
color: {
|
||||
switch (control.temprament) {
|
||||
case CallPageButton.Neutral:
|
||||
return Kirigami.Theme.textColor
|
||||
case CallPageButton.Constructive:
|
||||
return Kirigami.Theme.positiveTextColor
|
||||
case CallPageButton.Destructive:
|
||||
return Kirigami.Theme.negativeTextColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
color: {
|
||||
if (control.checked) {
|
||||
return Kirigami.Theme.focusColor
|
||||
}
|
||||
|
||||
switch (control.temprament) {
|
||||
case CallPageButton.Neutral:
|
||||
return Kirigami.Theme.backgroundColor
|
||||
case CallPageButton.Constructive:
|
||||
return Kirigami.Theme.positiveBackgroundColor
|
||||
case CallPageButton.Destructive:
|
||||
return Kirigami.Theme.negativeBackgroundColor
|
||||
}
|
||||
}
|
||||
border.color: Kirigami.Theme.focusColor
|
||||
border.width: control.visualFocus ? 2 : 0
|
||||
radius: height/2
|
||||
|
||||
Rectangle {
|
||||
visible: control.shimmering
|
||||
anchors.fill: parent
|
||||
radius: height/2
|
||||
|
||||
gradient: control.shimmering ? shimmerGradient : null
|
||||
}
|
||||
}
|
||||
}
|
||||
QQC2.Label {
|
||||
text: control.text
|
||||
font: Kirigami.Theme.smallFont
|
||||
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
import org.freedesktop.gstreamer.GLVideoItem 1.0
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
Rectangle {
|
||||
id: videoStreamDelegate
|
||||
|
||||
implicitWidth: height / 9 * 16
|
||||
implicitHeight: 300
|
||||
color: "black"
|
||||
radius: 10
|
||||
|
||||
QQC2.Label {
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: "white"
|
||||
text: model.object.user.id
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
Loader {
|
||||
active: model.object.hasCamera
|
||||
Layout.maximumWidth: parent.width
|
||||
Layout.maximumHeight: parent.height
|
||||
Layout.preferredHeight: parent.height
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
onActiveChanged: {
|
||||
if (active) {
|
||||
model.object.initCamera(camera)
|
||||
}
|
||||
}
|
||||
Component.onCompleted: if (active) model.object.initCamera(camera)
|
||||
GstGLVideoItem {
|
||||
id: camera
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
active: false
|
||||
Layout.maximumWidth: parent.width
|
||||
Layout.maximumHeight: parent.height
|
||||
Layout.preferredHeight: parent.height
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
GstGLVideoItem {
|
||||
id: screenCast
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
Component.onCompleted: {
|
||||
model.object.initCamera(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2022 Carson Black <uhhadd@gmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
TimelineContainer {
|
||||
id: root
|
||||
|
||||
width: ListView.view.width
|
||||
|
||||
innerObject: QQC2.Control {
|
||||
Layout.leftMargin: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing : 0
|
||||
padding: Kirigami.Units.gridUnit*2
|
||||
|
||||
contentItem: QQC2.Label {
|
||||
text: root.author.isLocalUser ? i18n("Outgoing Call") : i18n("Incoming Call")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,18 +11,15 @@ import org.kde.kirigami 2.15 as Kirigami
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
DelegateChooser {
|
||||
id: root
|
||||
role: "delegateType"
|
||||
property var room
|
||||
|
||||
DelegateChoice {
|
||||
roleValue: MessageEventModel.State
|
||||
delegate: StateDelegate {}
|
||||
}
|
||||
|
||||
DelegateChoice {
|
||||
roleValue: MessageEventModel.CallInvite
|
||||
delegate: CallInviteDelegate {}
|
||||
}
|
||||
|
||||
DelegateChoice {
|
||||
roleValue: MessageEventModel.Emote
|
||||
delegate: MessageDelegate {}
|
||||
@@ -82,6 +79,12 @@ DelegateChooser {
|
||||
roleValue: MessageEventModel.Location
|
||||
delegate: LocationDelegate {}
|
||||
}
|
||||
DelegateChoice {
|
||||
roleValue: MessageEventModel.LiveLocation
|
||||
delegate: LiveLocationDelegate {
|
||||
room: root.room
|
||||
}
|
||||
}
|
||||
|
||||
DelegateChoice {
|
||||
roleValue: MessageEventModel.Other
|
||||
|
||||
91
src/qml/Component/Timeline/LiveLocationDelegate.qml
Normal file
91
src/qml/Component/Timeline/LiveLocationDelegate.qml
Normal file
@@ -0,0 +1,91 @@
|
||||
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
||||
// SPDX-FileCopyrightText: 2023 Volker Krause <vkrause@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtLocation 5.15
|
||||
import QtPositioning 5.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
/**
|
||||
* @brief A timeline delegate for a location message.
|
||||
*
|
||||
* @inherit TimelineContainer
|
||||
*/
|
||||
TimelineContainer {
|
||||
id: root
|
||||
|
||||
property alias room: liveLocationModel.room
|
||||
|
||||
ColumnLayout {
|
||||
Layout.maximumWidth: root.contentMaxWidth
|
||||
Layout.preferredWidth: root.contentMaxWidth
|
||||
LiveLocationsModel {
|
||||
id: liveLocationModel
|
||||
eventId: root.eventId
|
||||
}
|
||||
Map {
|
||||
id: map
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: root.contentMaxWidth / 16 * 9
|
||||
|
||||
center: QtPositioning.coordinate(liveLocationModel.boundingBox.y, liveLocationModel.boundingBox.x)
|
||||
zoomLevel: 15
|
||||
|
||||
plugin: OsmLocationPlugin.plugin
|
||||
onCopyrightLinkActivated: Qt.openUrlExternally(link)
|
||||
|
||||
MapItemView {
|
||||
model: liveLocationModel
|
||||
delegate: MapQuickItem {
|
||||
anchorPoint.x: sourceItem.width / 2
|
||||
anchorPoint.y: sourceItem.height
|
||||
coordinate: QtPositioning.coordinate(model.latitude, model.longitude)
|
||||
autoFadeIn: false
|
||||
sourceItem: Kirigami.Icon {
|
||||
width: height
|
||||
height: Kirigami.Units.iconSizes.huge
|
||||
source: "gps"
|
||||
isMask: true
|
||||
color: model.isLive ? Kirigami.Theme.highlightColor : Kirigami.Theme.disabledTextColor
|
||||
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn: parent
|
||||
anchors.verticalCenterOffset: -parent.height / 8
|
||||
visible: model.asset === "m.pin"
|
||||
width: height
|
||||
height: parent.height / 3 + 1
|
||||
source: "pin"
|
||||
isMask: true
|
||||
color: parent.color
|
||||
}
|
||||
Kirigami.Avatar {
|
||||
anchors.centerIn: parent
|
||||
anchors.verticalCenterOffset: -parent.height / 8
|
||||
visible: model.asset === "m.self"
|
||||
width: height
|
||||
height: parent.height / 3 + 1
|
||||
name: model.author.displayName
|
||||
source: model.author.avatarSource
|
||||
color: model.author.color
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onLongPressed: openMessageContext("")
|
||||
}
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.RightButton
|
||||
onTapped: openMessageContext("")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,10 +50,10 @@ Flow {
|
||||
Kirigami.Theme.inherit: false
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
radius: height / 2
|
||||
shadow.size: Kirigami.Units.smallSpacing
|
||||
shadow.color: !model.hasLocalUser ? Qt.rgba(0.0, 0.0, 0.0, 0.10) : Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
|
||||
border.color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15)
|
||||
border.width: 1
|
||||
shadow {
|
||||
size: Kirigami.Units.smallSpacing
|
||||
color: !model.hasLocalUser ? Qt.rgba(0.0, 0.0, 0.0, 0.10) : Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: reactionClicked(model.reaction)
|
||||
|
||||
@@ -520,7 +520,9 @@ ColumnLayout {
|
||||
anchors.fill: parent
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
color: {
|
||||
if (root.author.isLocalUser) {
|
||||
if (mainContainer.hovered) {
|
||||
return Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.15)
|
||||
} else if (root.author.isLocalUser) {
|
||||
return Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.15)
|
||||
} else if (root.showHighlight) {
|
||||
return Kirigami.Theme.positiveBackgroundColor
|
||||
@@ -528,11 +530,11 @@ ColumnLayout {
|
||||
return Kirigami.Theme.backgroundColor
|
||||
}
|
||||
}
|
||||
radius: Kirigami.Units.smallSpacing
|
||||
shadow.size: Kirigami.Units.smallSpacing
|
||||
shadow.color: root.showHighlight ? Qt.rgba(0.0, 0.0, 0.0, 0.10) : Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
|
||||
border.color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15)
|
||||
border.width: 1
|
||||
radius: Kirigami.Units.largeSpacing
|
||||
shadow {
|
||||
size: Kirigami.Units.smallSpacing
|
||||
color: root.isHighlighted ? Qt.rgba(0.0, 0.0, 0.0, 0.10) : Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
enabled: isTemporaryHighlighted
|
||||
@@ -543,7 +545,7 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
visible: mainContainer.hovered
|
||||
visible: mainContainer.hovered && Config.compactLayout
|
||||
color: Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.15)
|
||||
radius: Kirigami.Units.smallSpacing
|
||||
}
|
||||
|
||||
@@ -173,6 +173,7 @@ QQC2.ScrollView {
|
||||
}
|
||||
|
||||
delegate: EventDelegate {
|
||||
room: root.currentRoom
|
||||
}
|
||||
|
||||
QQC2.RoundButton {
|
||||
|
||||
@@ -7,6 +7,8 @@ import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
QQC2.Dialog {
|
||||
id: confirmEncryptionDialog
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
Kirigami.Page {
|
||||
id: deleteSheet
|
||||
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
import QtQuick.Layouts 1.12
|
||||
|
||||
import org.kde.kirigami 2.14 as Kirigami
|
||||
|
||||
import QtGraphicalEffects 1.15
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
Kirigami.Page {
|
||||
id: page
|
||||
|
||||
title: CallManager.hasInvite ? i18n("Incoming Call")
|
||||
: CallManager.isInviting ? i18n("Calling")
|
||||
: CallManager.state == CallSession.Initiating ? i18n("Configuring Call")
|
||||
: i18n("Call")
|
||||
|
||||
ColumnLayout {
|
||||
id: column
|
||||
anchors.fill: parent
|
||||
|
||||
RowLayout {
|
||||
id: streams
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Repeater {
|
||||
id: videos
|
||||
model: CallManager.callParticipants
|
||||
delegate: VideoStreamDelegate {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Kirigami.Avatar {
|
||||
visible: videos.count === 0
|
||||
Layout.preferredWidth: Kirigami.Units.iconSizes.huge
|
||||
Layout.preferredHeight: Kirigami.Units.iconSizes.huge
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
name: CallManager.room.displayName
|
||||
source: "image://mxc/" + CallManager.room.avatarMediaId
|
||||
}
|
||||
|
||||
//QQC2.Label {
|
||||
//text: CallManager.remoteUser.displayName
|
||||
|
||||
//horizontalAlignment: Text.AlignHCenter
|
||||
//Layout.fillWidth: true
|
||||
//}
|
||||
|
||||
//QQC2.Label {
|
||||
//text: CallManager.room.displayName
|
||||
|
||||
//horizontalAlignment: Text.AlignHCenter
|
||||
//Layout.fillWidth: true
|
||||
//}
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
id: buttonRow
|
||||
spacing: Kirigami.Units.gridUnit
|
||||
|
||||
CallPageButton {
|
||||
text: i18n("Accept")
|
||||
icon.name: "call-start"
|
||||
shimmering: true
|
||||
temprament: CallPageButton.Constructive
|
||||
visible: CallManager.globalState === CallManager.INCOMING
|
||||
|
||||
onClicked: {
|
||||
visible = false; //TODO declarify
|
||||
CallManager.acceptCall()
|
||||
}
|
||||
}
|
||||
CallPageButton {
|
||||
text: checked ? i18n("Disable Camera") : i18n("Enable Camera")
|
||||
icon.name: checked ? "camera-on" : "camera-off"
|
||||
checkable: true
|
||||
onToggled: CallManager.toggleCamera()
|
||||
}
|
||||
CallPageButton {
|
||||
text: checked ? i18n("Unmute Speaker") : i18n("Mute Speaker")
|
||||
icon.name: checked ? "audio-volume-muted" : "audio-speakers-symbolic"
|
||||
checkable: true
|
||||
}
|
||||
CallPageButton {
|
||||
text: checked ? i18n("Unmute Microphone") : i18n("Mute Microphone")
|
||||
icon.name: checked ? "microphone-sensitivity-muted" : "microphone-sensitivity-high"
|
||||
checkable: true
|
||||
checked: CallManager.muted
|
||||
|
||||
onToggled: CallManager.muted = !CallManager.muted
|
||||
}
|
||||
CallPageButton {
|
||||
text: i18n("Configure Devices")
|
||||
icon.name: "settings-configure"
|
||||
onClicked: callConfigurationSheet.open()
|
||||
}
|
||||
CallPageButton {
|
||||
id: denyButton
|
||||
visible: CallManager.globalState === CallManager.INCOMING
|
||||
text: i18n("Deny")
|
||||
icon.name: "call-stop"
|
||||
shimmering: true
|
||||
temprament: CallPageButton.Destructive
|
||||
|
||||
onClicked: CallManager.hangupCall()
|
||||
}
|
||||
CallPageButton {
|
||||
visible: !denyButton.visible
|
||||
text: CallManager.isInviting ? i18n("Cancel") : i18n("Hang Up")
|
||||
icon.name: "call-stop"
|
||||
shimmering: CallManager.isInviting
|
||||
temprament: CallPageButton.Destructive
|
||||
|
||||
onClicked: CallManager.hangupCall()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: CallManager
|
||||
function onCallEnded() {
|
||||
page.closeDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,16 +52,6 @@ Kirigami.Page {
|
||||
}
|
||||
}
|
||||
|
||||
actions.main: Kirigami.Action {
|
||||
text: i18n("Call")
|
||||
icon.name: "call-start"
|
||||
visible: Controller.callsSupported && root.currentRoom.joinedCount === 2
|
||||
onTriggered: {
|
||||
CallManager.startCall(root.currentRoom, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loader {
|
||||
id: timelineViewLoader
|
||||
anchors.fill: parent
|
||||
|
||||
@@ -5,6 +5,8 @@ import QtQuick 2.15
|
||||
import org.kde.kirigami 2.18 as Kirigami
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
Kirigami.CategorizedSettings {
|
||||
id: root
|
||||
property NeoChatRoom room
|
||||
|
||||
@@ -44,7 +44,7 @@ Kirigami.ScrollablePage {
|
||||
sortRole: "powerLevel"
|
||||
sortOrder: Qt.DescendingOrder
|
||||
filterRowCallback: function(source_row, source_parent) {
|
||||
let powerLevelRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), Qt.UserRole + 5)
|
||||
let powerLevelRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), UserListModel.PowerLevelRole)
|
||||
return powerLevelRole > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
title: i18nc("@title:window", "Calls")
|
||||
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
ColumnLayout {
|
||||
MobileForm.FormCard {
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
Layout.fillWidth: true
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
MobileForm.FormCardHeader {
|
||||
title: i18n("Incoming Calls")
|
||||
}
|
||||
MobileForm.FormCheckDelegate {
|
||||
text: i18n("Ring")
|
||||
checked: Config.ring // TODO
|
||||
enabled: !Config.isRingImmutable //TODO
|
||||
onToggled: {
|
||||
Config.ring = checked
|
||||
Config.sync()
|
||||
}
|
||||
}
|
||||
MobileForm.FormTextFieldDelegate {
|
||||
label: i18n("Ringtone")
|
||||
text: Config.ringtone
|
||||
enabled: true //TODO
|
||||
onEditingFinished: {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
//TODO file chooser
|
||||
}
|
||||
}
|
||||
|
||||
MobileForm.FormCard {
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
Layout.fillWidth: true
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
MobileForm.FormCardHeader {
|
||||
title: i18n("Default Devices")
|
||||
}
|
||||
|
||||
MobileForm.FormComboBoxDelegate {
|
||||
text: i18n("Microphone")
|
||||
description: i18n("This microphone will be used by default during calls. You can also switch the microphone during calls.")
|
||||
model: AudioSources
|
||||
enabled: true //TODO
|
||||
onCurrentIndexChanged: {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
MobileForm.FormComboBoxDelegate {
|
||||
text: i18n("Camera")
|
||||
description: i18n("This camera will be used by default during calls. You can also switch the camera during calls.")
|
||||
model: VideoSources
|
||||
enabled: true // TODO
|
||||
onCurrentIndexChanged: {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,12 +58,6 @@ Kirigami.CategorizedSettings {
|
||||
icon.name: "computer"
|
||||
page: Qt.resolvedUrl("DevicesPage.qml")
|
||||
},
|
||||
Kirigami.SettingAction {
|
||||
actionName: "calls"
|
||||
text: i18n("Calls")
|
||||
iconName: "call-start"
|
||||
page: Qt.resolvedUrl("CallConfigurationPage.qml")
|
||||
},
|
||||
Kirigami.SettingAction {
|
||||
actionName: "aboutNeochat"
|
||||
text: i18n("About NeoChat")
|
||||
|
||||
@@ -43,18 +43,6 @@ Kirigami.ApplicationWindow {
|
||||
source: Qt.resolvedUrl("qrc:/GlobalMenu.qml")
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Controller.callsSupported ? CallManager : undefined
|
||||
|
||||
function onGlobalStateChanged() {
|
||||
if (CallManager.globalState === CallManager.OUTGOING || CallManager.globalState === CallManager.INCOMING) {
|
||||
pageStack.pushDialogLayer("qrc:/CallPage.qml", {}, {
|
||||
title: i18n("Call")
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This timer allows to batch update the window size change to reduce
|
||||
// the io load and also work around the fact that x/y/width/height are
|
||||
// changed when loading the page and overwrite the saved geometry from
|
||||
|
||||
@@ -105,7 +105,6 @@
|
||||
<file alias="GlobalNotificationsPage.qml">qml/Settings/GlobalNotificationsPage.qml</file>
|
||||
<file alias="NotificationRuleItem.qml">qml/Settings/NotificationRuleItem.qml</file>
|
||||
<file alias="AppearanceSettingsPage.qml">qml/Settings/AppearanceSettingsPage.qml</file>
|
||||
<file alias="CallConfigurationPage.qml">qml/Settings/CallConfigurationPage.qml</file>
|
||||
<file alias="AccountsPage.qml">qml/Settings/AccountsPage.qml</file>
|
||||
<file alias="AccountEditorPage.qml">qml/Settings/AccountEditorPage.qml</file>
|
||||
<file alias="DevicesPage.qml">qml/Settings/DevicesPage.qml</file>
|
||||
@@ -128,9 +127,6 @@
|
||||
<file alias="AvatarTabButton.qml">qml/Component/AvatarTabButton.qml</file>
|
||||
<file alias="SpaceDrawer.qml">qml/Page/RoomList/SpaceDrawer.qml</file>
|
||||
<file alias="OsmLocationPlugin.qml">qml/Component/Timeline/OsmLocationPlugin.qml</file>
|
||||
<file alias="CallPageButton.qml">qml/Component/Call/CallPageButton.qml</file>
|
||||
<file alias="VideoStreamDelegate.qml">qml/Component/Call/VideoStreamDelegate.qml</file>
|
||||
<file alias="CallPage.qml">qml/Page/CallPage.qml</file>
|
||||
<file alias="CallInviteDelegate.qml">qml/Component/Timeline/CallInviteDelegate.qml</file>
|
||||
<file alias="LiveLocationDelegate.qml">qml/Component/Timeline/LiveLocationDelegate.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
Reference in New Issue
Block a user