Compare commits

..

9 Commits

Author SHA1 Message Date
f39afdac4c misc: add vscode project settings file
- specifies some include paths
- enforces LF eol
- encourages clang-format use
- adds a comment regarding the IPC task

Note: currently GNU/Linux-specific

Change-Id: Ib208aca33026bf1c15a3ef18020805ceb20aa55f
2024-04-10 15:29:00 -04:00
690f2dd85c misc: add vscode task/launch configurations
This is a good start, but will need to be adapted for other platforms and improved over time.

Change-Id: Ib64046e852c3aa9cc9b492d0af8cee33ee1ff5de
2024-04-10 15:19:14 -04:00
bd45d6a406 misc: fix argument warning for non-debug builds
The `test` option is not used in non-debug builds.

Change-Id: I25eef5b414f987ae4acc435213173f8c78390866
2024-04-09 11:26:34 -05:00
5b92e4708a splitviews: fix non-transparent handle hover zone
This commit adds configurable size to the handle, as it will likely be made transparent soon.

Gitlab: #1611

Change-Id: I1574089d57b5993b59e29732e6a0c573ef91f606
2024-04-09 12:24:23 -04:00
63c01f1439 misc: filter some noisy logs
Change-Id: I799e8f66e2008323817c73292f94e8c625564d67
2024-04-08 15:35:31 -04:00
73aeb02ebd misc: bump daemon submodule
Change-Id: I800aad6362be0124a33904b834ff8e04b560d6a8
2024-04-08 15:11:47 -04:00
9d91317089 snap: add libpipewire to build dependencies
Change-Id: Ie2d24de1aabe59c9506786cfb5fa18fcf4e8cad2
2024-04-07 12:32:32 -04:00
474bc5f6a4 incalllocalvideo: allow resizing/changing opacity of local video
This feature was accidentally removed in a recent refactoring of the
local video preview:
https://review.jami.net/c/jami-client-qt/+/27740

Change-Id: I8b621d4f692124311f0807d1bc0be0e96717a499
2024-04-04 11:39:44 -04:00
f5b64e955b i18n: automatic bump
Change-Id: I0589f432edc46aba5effaaca85f1a53df00760dd
2024-04-01 16:42:26 -04:00
19 changed files with 353 additions and 155 deletions

13
.gitignore vendored
View File

@ -1,9 +1,18 @@
*.user
doc/Doxyfile
### VisualStudioCode ###
.vscode/**/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
### VisualStudioCode Patch ###
# Ignore all local history of files
**/.history
GeneratedFiles/
.vs/
.vscode/
x64/
x86/
[wW]in32/

78
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,78 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Jami-Tests-Run",
"type": "cppdbg",
"request": "launch",
"program": "/usr/bin/ctest",
"args": ["-V", "-R"],
"cwd": "${workspaceFolder}/build/tests",
"externalConsole": false,
"environment": [
{
"name": "HOME",
"value": "/tmp"
}
]
},
{
"name": "Jami-Client",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/jami",
"args": [
"-d",
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "cmake-build",
"miDebuggerPath": "/usr/bin/gdb",
},
{
"name": "Jami-Daemon-Debug",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/daemon/bin/dbus/jamid",
"args": [
"-cdp",
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "cmake-build",
"miDebuggerPath": "/usr/bin/gdb",
}
],
"compounds": [
{
// Using this configuration will require manually reconfiguring the project using
// build.py --no-libwrap, otherwise the daemon executable will not be built and the
// client will not be built with ENABLE_LIBWRAP=False.
"name": "Jami-Client-IPC",
"configurations": [
"Jami-Daemon-Debug",
"Jami-Client",
]
}
]
}

15
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,15 @@
{
"C_Cpp.default.includePath": [
"${default}",
"${workspaceFolder}/**",
"/usr/lib/libqt-jami/include/**",
"/usr/lib64/qt-jami/include/**",
],
"C_Cpp.default.cppStandard": "c++17",
"C_Cpp.default.cStandard": "c11",
"cmake.configureOnOpen": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "xaver.clang-format",
"files.eol": "\n",
"cSpell.enabled": false,
}

52
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,52 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "cmake-configure",
"type": "shell",
"command": "cmake",
"args": [
"-S", ".",
"-B", "build",
"-DCMAKE_BUILD_TYPE=Debug",
"-DCMAKE_PREFIX_PATH=\"/usr/lib64/qt-jami;/usr/lib/libqt-jami\"",
"-DBUILD_TESTING=True"
],
"group": "build",
"problemMatcher": [],
"detail": "Generate the build system files with CMake."
},
{
"label": "cmake-build",
"type": "shell",
"command": "cmake",
"args": [
"--build", "build",
"-j$(nproc)",
],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
],
"detail": "Compile the project using the generated build system.",
"dependsOn": [
"cmake-configure"
]
},
{
"label": "cmake-clean",
"type": "shell",
"command": "rm",
"args": [
"-rf",
"build"
],
"group": "build",
"problemMatcher": [],
"detail": "Clean the build directory."
}
]
}

2
daemon

Submodule daemon updated: 32f39e6548...59a8e41ca8

View File

@ -1,5 +1,5 @@
ARG RISK=edge
ARG UBUNTU=focal
ARG UBUNTU=jammy
FROM ubuntu:$UBUNTU as builder
ARG RISK

View File

@ -168,7 +168,7 @@ package-repositories:
components: [main]
suites: [jami]
key-id: A295D773307D25A33AE72F2F64CD5FA175348F84
url: https://dl.jami.net/nightly/ubuntu_20.04/
url: https://dl.jami.net/nightly/ubuntu_22.04/
parts:
desktop-launch:
@ -304,6 +304,7 @@ parts:
- libswscale-dev
- libva-dev
- libvdpau-dev
- libpipewire-0.3-dev
- libargon2-0-dev # opendht
- libexpat1-dev
- libjsoncpp-dev
@ -326,7 +327,7 @@ parts:
- libegl1
- libgbm1
- libgudev-1.0-0
- libjsoncpp1
- libjsoncpp25
- libllvm12
- libminizip1
- libnm0

View File

@ -20,6 +20,8 @@
#include "appsettingsmanager.h"
#include "global.h"
#include <QCoreApplication>
#include <QLibraryInfo>
@ -101,7 +103,7 @@ AppSettingsManager::loadTranslations()
installedTr_.clear();
QString locale_name = getLanguage();
qDebug() << QString("Using locale: %1").arg(locale_name);
C_INFO << QString("Using locale: %1").arg(locale_name);
QString locale_lang = locale_name.split('_')[0];
QTranslator* qtTranslator_lang = new QTranslator(qApp);

View File

@ -1,83 +1,97 @@
/*
* Copyright (C) 2024 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
// A SplitView that supports dynamic RTL and splitView state saving.
SplitView {
id: root
property bool isRTL: UtilsAdapter.isRTL
property bool isSinglePane: false
property bool isSwapped: false
onIsRTLChanged: {
if (isRTL && isSinglePane && !isSwapped)
return
if ((isRTL && !isSwapped) || (!isRTL && isSwapped))
swapItems()
}
onIsSinglePaneChanged: {
if (isSwapped || isRTL)
swapItems()
}
property string splitViewStateKey: objectName
property bool autoManageState: !(parent instanceof BaseView)
function saveSplitViewState() {
UtilsAdapter.setAppValue("sv_" + splitViewStateKey, root.saveState());
}
function restoreSplitViewState() {
root.restoreState(UtilsAdapter.getAppValue("sv_" + splitViewStateKey));
}
onResizingChanged: if (!resizing)
saveSplitViewState()
onVisibleChanged: {
if (!autoManageState)
return;
visible ? restoreSplitViewState() : saveSplitViewState();
}
function swapItems() {
isSwapped = !isSwapped
var qqci = children[0];
if (qqci.children.length > 1) {
// swap the children
var tempPane = qqci.children[0];
qqci.children[0] = qqci.children[1];
qqci.children.push(tempPane);
}
}
handle: Rectangle {
visible: !isSinglePane
implicitWidth: JamiTheme.splitViewHandlePreferredWidth
implicitHeight: root.height
color: JamiTheme.primaryBackgroundColor
Rectangle {
anchors.left: parent.left
implicitWidth: 1
implicitHeight: root.height
color: JamiTheme.tabbarBorderColor
}
}
}
/*
* Copyright (C) 2024 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick
import QtQuick.Controls
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
// A SplitView that supports dynamic RTL and splitView state saving.
SplitView {
id: control
property bool isRTL: UtilsAdapter.isRTL
property bool isSinglePane: false
property bool isSwapped: false
property real handleSize: 1
onIsRTLChanged: {
if (isRTL && isSinglePane && !isSwapped)
return
if ((isRTL && !isSwapped) || (!isRTL && isSwapped))
swapItems()
}
onIsSinglePaneChanged: {
if (isSwapped || isRTL)
swapItems()
}
property string splitViewStateKey: objectName
property bool autoManageState: !(parent instanceof BaseView)
function saveSplitViewState() {
UtilsAdapter.setAppValue("sv_" + splitViewStateKey, control.saveState());
}
function restoreSplitViewState() {
control.restoreState(UtilsAdapter.getAppValue("sv_" + splitViewStateKey));
}
onResizingChanged: if (!resizing)
saveSplitViewState()
onVisibleChanged: {
if (!autoManageState)
return;
visible ? restoreSplitViewState() : saveSplitViewState();
}
function swapItems() {
isSwapped = !isSwapped
var qqci = children[0];
if (qqci.children.length > 1) {
// swap the children
var tempPane = qqci.children[0];
qqci.children[0] = qqci.children[1];
qqci.children.push(tempPane);
}
}
handle: Rectangle {
id: handleRoot
readonly property int defaultSize: control.handleSize
implicitWidth: control.orientation === Qt.Horizontal ? handleRoot.defaultSize : control.width
implicitHeight: control.orientation === Qt.Horizontal ? control.height : handleRoot.defaultSize
color: JamiTheme.tabbarBorderColor
containmentMask: Item {
// In the default configuration, the total handle size is the sum of the default size of the
// handle and the extra handle size (4). If the layout is not right-to-left (RTL), the handle
// is positioned at 0 on the X-axis, otherwise it's positioned to the left by the extra handle
// size (4 pixels). This is done to make it easier to grab small scroll-view handles that are
// adjacent to the SplitView handle. Note: vertically oriented handles are not offset.
readonly property real extraHandleSize: 4
readonly property real handleXPosition: !isRTL ? 0 : -extraHandleSize
readonly property real handleSize: handleRoot.defaultSize + extraHandleSize
x: control.orientation === Qt.Horizontal ? handleXPosition : 0
width: control.orientation === Qt.Horizontal ? handleSize : handleRoot.width
height: control.orientation === Qt.Horizontal ? handleRoot.height : handleSize
}
}
}

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "global.h"
#ifndef _WIN32
#include <glib.h>
#include <gio/gio.h>
@ -171,10 +173,10 @@ static void
logConnectionInfo(NMActiveConnection* connection)
{
if (connection) {
qDebug() << "primary network connection:" << nm_active_connection_get_uuid(connection)
<< "default: " << (nm_active_connection_get_default(connection) ? "yes" : "no");
C_INFO << "primary network connection:" << nm_active_connection_get_uuid(connection)
<< "default: " << (nm_active_connection_get_default(connection) ? "yes" : "no");
} else {
qWarning() << "no primary network connection detected, check network settings";
C_WARN << "no primary network connection detected, check network settings";
}
}
@ -191,11 +193,10 @@ nmClientCallback(G_GNUC_UNUSED GObject* source_object, GAsyncResult* result, Con
{
GError* error = nullptr;
if (auto nm_client = nm_client_new_finish(result, &error)) {
qDebug() << "NetworkManager client initialized, version: "
<< nm_client_get_version(nm_client)
<< ", daemon running:" << (nm_client_get_nm_running(nm_client) ? "yes" : "no")
<< ", networking enabled:"
<< (nm_client_networking_get_enabled(nm_client) ? "yes" : "no");
C_INFO << "NetworkManager client initialized, version: " << nm_client_get_version(nm_client)
<< ", daemon running:" << (nm_client_get_nm_running(nm_client) ? "yes" : "no")
<< ", networking enabled:"
<< (nm_client_networking_get_enabled(nm_client) ? "yes" : "no");
auto connection = nm_client_get_primary_connection(nm_client);
logConnectionInfo(connection);
@ -205,7 +206,7 @@ nmClientCallback(G_GNUC_UNUSED GObject* source_object, GAsyncResult* result, Con
cm);
} else {
qWarning() << "error initializing NetworkManager client: " << error->message;
C_WARN << "error initializing NetworkManager client: " << error->message;
g_clear_error(&error);
}
}
@ -222,7 +223,7 @@ ConnectivityMonitor::ConnectivityMonitor(QObject* parent)
ConnectivityMonitor::~ConnectivityMonitor()
{
qDebug() << "Destroying connectivity monitor";
C_DBG << "Destroying connectivity monitor";
}
bool

View File

@ -18,6 +18,7 @@
#include "currentcall.h"
#include "callparticipantsmodel.h"
#include "global.h"
#include <api/callparticipantsmodel.h>
#include <api/devicemodel.h>
@ -348,7 +349,7 @@ CurrentCall::onCurrentAccountIdChanged()
auto& accInfo = lrcInstance_->getCurrentAccountInfo();
set_isSIP(accInfo.profileInfo.type == profile::Type::SIP);
} catch (const std::exception& e) {
qWarning() << "Can't update current call type" << e.what();
C_DBG << "Can't update current call type" << e.what();
}
connectModel();

View File

@ -162,6 +162,8 @@ MainApplication::MainApplication(int& argc, char** argv)
"libclient.debug=false\n"
"qt.*=false\n"
"qml.debug=false\n"
"default.debug=false\n"
"client.debug=false\n"
"\n");
// These can be set in the environment as well.
// e.g. QT_LOGGING_RULES="*.debug=false;qml.debug=true"
@ -423,7 +425,8 @@ MainApplication::initQmlLayer()
&screenInfo_,
this);
QUrl url;
QUrl url = u"qrc:/MainApplicationWindow.qml"_qs;
#ifdef QT_DEBUG
if (parser_.isSet("test")) {
// List the QML files in the project source tree.
const auto targetTestComponent = findResource(parser_.value("test"));
@ -437,9 +440,8 @@ MainApplication::initQmlLayer()
engine_->rootContext()->setContextProperty("testWidth", testWidth);
engine_->rootContext()->setContextProperty("testHeight", testHeight);
url = u"qrc:/ComponentTestWindow.qml"_qs;
} else {
url = u"qrc:/MainApplicationWindow.qml"_qs;
}
#endif
QObject::connect(
engine_.get(),
&QQmlApplicationEngine::objectCreationFailed,
@ -449,7 +451,7 @@ MainApplication::initQmlLayer()
engine_->load(url);
// Report the render interface used.
C_DBG << "Main window loaded using" << getRenderInterfaceString();
C_INFO << "Main window loaded using" << getRenderInterfaceString();
}
void

View File

@ -222,7 +222,7 @@ Rectangle {
onExtrasPanelWidthChanged: {
resolvePanes();
// This range should ensure that the panel won't restore to maximized.
if (extrasPanelWidth !== 0 && extrasPanelWidth !== width) {
if (extrasPanelWidth !== 0 && extrasPanelWidth !== this.width) {
console.debug("Saving previous extras panel width: %1".arg(extrasPanelWidth));
previousExtrasPanelWidth = extrasPanelWidth;
}

View File

@ -43,8 +43,14 @@ LocalVideo {
visibilityCondition: (CurrentCall.isSharing || !CurrentCall.isVideoMuted) &&
!CurrentCall.isConference
// Keep the area of the preview a proportion of the screen size plus a
// modifier to allow the user to scale it.
readonly property real containerArea: container.width * container.height
property real scalingFactor: 1
width: Math.sqrt(containerArea / 16) * scalingFactor
height: width * invAspectRatio
width: Math.max(container.width / 5, JamiTheme.minimumPreviewWidth)
flip: CurrentCall.flipSelf && !CurrentCall.isSharing
blurRadius: hidden ? 25 : 0
@ -62,6 +68,20 @@ LocalVideo {
// Animate the hiddenSize with a Behavior.
Behavior on sideMargin { NumberAnimation { duration: 250; easing.type: Easing.OutExpo }}
readonly property bool onLeft: state.indexOf("left") !== -1
MouseArea {
anchors.fill: parent
enabled: !localPreview.hidden
onWheel: function(event) {
const delta = event.angleDelta.y / 120 * 0.1;
if (event.modifiers & Qt.ControlModifier) {
parent.opacity = JamiQmlUtils.clamp(parent.opacity + delta, 0.25, 1);
} else {
localPreview.scalingFactor = JamiQmlUtils.clamp(localPreview.scalingFactor + delta, 0.5, 4);
}
}
}
PushButton {
id: hidePreviewButton
objectName: "hidePreviewButton"

View File

@ -18,6 +18,8 @@
#include "screensaver.h"
#include "global.h"
#include <QDebug>
ScreenSaver::ScreenSaver(QObject* parent)
@ -31,8 +33,7 @@ ScreenSaver::ScreenSaver(QObject* parent)
}
#else
: QObject(parent)
{
}
{}
#endif
#ifdef Q_OS_LINUX
@ -50,7 +51,7 @@ ScreenSaver::createInterface(void)
services_[i],
sessionBus_);
if (screenSaverInterface_ && screenSaverInterface_->isValid()) {
qDebug() << "Screen saver dbus interface: " << services_[i];
C_INFO << "Screen saver dbus interface: " << services_[i];
return true;
}
}

View File

@ -19,6 +19,7 @@
#include "systemtray.h"
#include "appsettingsmanager.h"
#include "global.h"
#ifdef USE_LIBNOTIFY
#include <libnotify/notification.h>
@ -106,8 +107,8 @@ SystemTray::SystemTray(AppSettingsManager* settingsManager, QObject* parent)
char* spec = nullptr;
if (notify_get_server_info(&name, &vendor, &version, &spec)) {
qDebug() << QString("notify server name: %1, vendor: %2, version: %3, spec: %4")
.arg(name, vendor, version, spec);
C_INFO << QString("notify server name: %1, vendor: %2, version: %3, spec: %4")
.arg(name, vendor, version, spec);
}
// check notify server capabilities
@ -167,7 +168,7 @@ SystemTray::hideNotification(const QString& id)
// Close
GError* error = nullptr;
if (!notify_notification_close(notification->second.nn.get(), &error)) {
qWarning("could not close notification: %s", error->message);
C_WARN << QString("could not close notification: %1").arg(error->message);
g_clear_error(&error);
return false;
}
@ -235,7 +236,7 @@ SystemTray::showNotification(const QString& id,
GError* error = nullptr;
notify_notification_show(notification.get(), &error);
if (error) {
qWarning("failed to show notification: %s", error->message);
C_WARN << QString("failed to show notification: %1").arg(error->message);
g_clear_error(&error);
}
#else

View File

@ -24,6 +24,7 @@
#include "jamiavatartheme.h"
#include "lrcinstance.h"
#include "global.h"
#include <api/contact.h>
@ -488,7 +489,7 @@ Utils::conversationAvatar(LRCInstance* instance,
painter.drawImage(avatar.rect(), peerAAvatar);
painter.drawImage(avatar.rect(), peerBAvatar);
} catch (const std::exception& e) {
qDebug() << Q_FUNC_INFO << e.what();
C_DBG << e.what();
}
return avatar;
}

View File

@ -307,37 +307,37 @@ Jami will now quit.</source>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="90"/>
<source>Push-to-talk</source>
<translation type="unfinished"/>
<translation>Voki-toki</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="91"/>
<source>Enable push-to-talk</source>
<translation type="unfinished"/>
<translation>Omogućite voki-toki</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="92"/>
<source>Keyboard shortcut</source>
<translation type="unfinished"/>
<translation>Prečica na tastaturi</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="93"/>
<source>Change keyboard shortcut</source>
<translation type="unfinished"/>
<translation>Promenite prečicu na tastaturi</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="96"/>
<source>Change shortcut</source>
<translation type="unfinished"/>
<translation>Promenite prečicu</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="97"/>
<source>Press the key to be assigned to push-to-talk shortcut</source>
<translation type="unfinished"/>
<translation>Pritisnite taster da budete dodeljeni voki-toki prečici</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="98"/>
<source>Assign</source>
<translation type="unfinished"/>
<translation>Dodeli</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="101"/>
@ -597,7 +597,7 @@ Jami will now quit.</source>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="176"/>
<source>Extensions</source>
<translation type="unfinished"/>
<translation>Proširenja</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="186"/>
@ -850,7 +850,7 @@ The profile can be changed at all times from the account&apos;s settings.</sourc
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="480"/>
<source>Use native window frame (requires restart)</source>
<translation type="unfinished"/>
<translation>Koristite izvorni okvir prozora (zahteva ponovno pokretanje)</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="484"/>
@ -885,12 +885,12 @@ The profile can be changed at all times from the account&apos;s settings.</sourc
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="529"/>
<source>Content access error</source>
<translation type="unfinished"/>
<translation>Greška u pristupu sadržaju</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="530"/>
<source>Content not found</source>
<translation type="unfinished"/>
<translation>Sadržaj nije pronađen</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="593"/>
@ -900,22 +900,22 @@ The profile can be changed at all times from the account&apos;s settings.</sourc
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="594"/>
<source>This account is password encrypted, enter the password to generate a PIN code.</source>
<translation type="unfinished"/>
<translation>Ovaj nalog je šifrovan lozinkom, unesite lozinku da biste generisali PIN kod.</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="596"/>
<source>PIN expired</source>
<translation type="unfinished"/>
<translation>PIN je istekao</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="597"/>
<source>On another device</source>
<translation type="unfinished"/>
<translation>Na drugom uređaju</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="598"/>
<source>Install and launch Jami, select &quot;Import from another device&quot; and scan the QR code.</source>
<translation type="unfinished"/>
<translation>Instalirajte i pokrenite Jami, izaberite Uvezi sa drugog uređaja i skenirajte QR kod.</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="599"/>
@ -925,12 +925,12 @@ The profile can be changed at all times from the account&apos;s settings.</sourc
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="600"/>
<source>In Jami, scan QR code or manually enter the PIN.</source>
<translation type="unfinished"/>
<translation>U Jamiju, skenirajte QR kod ili ručno unesite PIN.</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="601"/>
<source>The PIN code is valid for: </source>
<translation type="unfinished"/>
<translation>PIN kod važi za:</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="604"/>
@ -4407,7 +4407,7 @@ connects to synchronize the conversation.</source>
<message>
<location filename="../src/app/utilsadapter.cpp" line="345"/>
<source>%1 Mbps</source>
<translation>%1 Мбпс</translation>
<translation>%1 Mbps</translation>
</message>
<message>
<location filename="../src/app/utilsadapter.cpp" line="345"/>
@ -4425,22 +4425,22 @@ connects to synchronize the conversation.</source>
<message>
<location filename="../src/libclient/contactmodel.cpp" line="498"/>
<source>Searching</source>
<translation>Трагајући...</translation>
<translation>Traženje</translation>
</message>
<message>
<location filename="../src/libclient/contactmodel.cpp" line="1030"/>
<source>Invalid ID</source>
<translation>Неважни идентификациони документ</translation>
<translation>Nevažeći ID</translation>
</message>
<message>
<location filename="../src/libclient/contactmodel.cpp" line="1033"/>
<source>Username not found</source>
<translation>Име корисника није пронађено</translation>
<translation>Korisničko ime nije pronađeno</translation>
</message>
<message>
<location filename="../src/libclient/contactmodel.cpp" line="1036"/>
<source>Couldn&apos;t lookup</source>
<translation>Не могу да тражим...</translation>
<translation>Nije moguće potražiti</translation>
</message>
</context>
<context>
@ -4448,7 +4448,7 @@ connects to synchronize the conversation.</source>
<message>
<location filename="../src/libclient/contactmodel.cpp" line="461"/>
<source>Bad URI scheme</source>
<translation>Лоша схема УРИ-а</translation>
<translation>Loša URI šema</translation>
</message>
</context>
</TS>

View File

@ -308,37 +308,37 @@ Jami will now quit.</source>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="90"/>
<source>Push-to-talk</source>
<translation type="unfinished"/>
<translation>Voki-toki</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="91"/>
<source>Enable push-to-talk</source>
<translation type="unfinished"/>
<translation>Omogućite voki-toki</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="92"/>
<source>Keyboard shortcut</source>
<translation type="unfinished"/>
<translation>Prečica na tastaturi</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="93"/>
<source>Change keyboard shortcut</source>
<translation type="unfinished"/>
<translation>Promenite prečicu na tastaturi</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="96"/>
<source>Change shortcut</source>
<translation type="unfinished"/>
<translation>Promenite prečicu</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="97"/>
<source>Press the key to be assigned to push-to-talk shortcut</source>
<translation type="unfinished"/>
<translation>Pritisnite taster da budete dodeljeni voki-toki prečici</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="98"/>
<source>Assign</source>
<translation type="unfinished"/>
<translation>Dodeli</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="101"/>
@ -598,7 +598,7 @@ Jami will now quit.</source>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="176"/>
<source>Extensions</source>
<translation type="unfinished"/>
<translation>Proširenja</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="186"/>
@ -850,7 +850,7 @@ The profile can be changed at all times from the account&apos;s settings.</sourc
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="480"/>
<source>Use native window frame (requires restart)</source>
<translation type="unfinished"/>
<translation>Koristite izvorni okvir prozora (zahteva ponovno pokretanje)</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="484"/>
@ -885,12 +885,12 @@ The profile can be changed at all times from the account&apos;s settings.</sourc
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="529"/>
<source>Content access error</source>
<translation type="unfinished"/>
<translation>Greška u pristupu sadržaju</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="530"/>
<source>Content not found</source>
<translation type="unfinished"/>
<translation>Sadržaj nije pronađen</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="593"/>
@ -900,22 +900,22 @@ The profile can be changed at all times from the account&apos;s settings.</sourc
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="594"/>
<source>This account is password encrypted, enter the password to generate a PIN code.</source>
<translation type="unfinished"/>
<translation>Ovaj nalog je šifrovan lozinkom, unesite lozinku da biste generisali PIN kod.</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="596"/>
<source>PIN expired</source>
<translation type="unfinished"/>
<translation>PIN je istekao</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="597"/>
<source>On another device</source>
<translation type="unfinished"/>
<translation>Na drugom uređaju</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="598"/>
<source>Install and launch Jami, select &quot;Import from another device&quot; and scan the QR code.</source>
<translation type="unfinished"/>
<translation>Instalirajte i pokrenite Jami, izaberite Uvezi sa drugog uređaja i skenirajte QR kod.</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="599"/>
@ -925,12 +925,12 @@ The profile can be changed at all times from the account&apos;s settings.</sourc
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="600"/>
<source>In Jami, scan QR code or manually enter the PIN.</source>
<translation type="unfinished"/>
<translation>U Jamiju, skenirajte QR kod ili ručno unesite PIN.</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="601"/>
<source>The PIN code is valid for: </source>
<translation type="unfinished"/>
<translation>PIN kod važi za:</translation>
</message>
<message>
<location filename="../src/app/net/jami/Constants/JamiStrings.qml" line="604"/>