From d84219c6b48a8e0e894340c2df08fea27ce1473b Mon Sep 17 00:00:00 2001
From: ababi <albert.babi@savoirfairelinux.com>
Date: Thu, 25 Feb 2021 17:23:36 +0100
Subject: [PATCH] misc: revise and catch exceptions thrown from lrc

Change-Id: I0e28f20ecb017267e74ef76fb922443e15e896e8
Gitlab: #308
---
 src/bannedlistmodel.cpp                       |  26 +-
 src/conversationsadapter.cpp                  |  10 +-
 src/moderatorlistmodel.cpp                    |  34 +-
 src/settingsadapter.cpp                       |   8 +-
 src/settingsview/components/VideoSettings.qml |   8 +-
 src/utils.cpp                                 |  23 +-
 src/utilsadapter.cpp                          | 723 +++++++++---------
 7 files changed, 430 insertions(+), 402 deletions(-)

diff --git a/src/bannedlistmodel.cpp b/src/bannedlistmodel.cpp
index 68caa29ac..a7700de5a 100644
--- a/src/bannedlistmodel.cpp
+++ b/src/bannedlistmodel.cpp
@@ -49,19 +49,23 @@ BannedListModel::columnCount(const QModelIndex& parent) const
 QVariant
 BannedListModel::data(const QModelIndex& index, int role) const
 {
-    auto contactList = lrcInstance_->getCurrentAccountInfo().contactModel->getBannedContacts();
-    if (!index.isValid() || contactList.size() <= index.row()) {
-        return QVariant();
-    }
+    try {
+        auto contactList = lrcInstance_->getCurrentAccountInfo().contactModel->getBannedContacts();
+        if (!index.isValid() || contactList.size() <= index.row()) {
+            return QVariant();
+        }
 
-    auto contactInfo = lrcInstance_->getCurrentAccountInfo().contactModel->getContact(
-        contactList.at(index.row()));
+        auto contactInfo = lrcInstance_->getCurrentAccountInfo().contactModel->getContact(
+            contactList.at(index.row()));
 
-    switch (role) {
-    case Role::ContactName:
-        return QVariant(contactInfo.registeredName);
-    case Role::ContactID:
-        return QVariant(contactInfo.profileInfo.uri);
+        switch (role) {
+        case Role::ContactName:
+            return QVariant(contactInfo.registeredName);
+        case Role::ContactID:
+            return QVariant(contactInfo.profileInfo.uri);
+        }
+    } catch (const std::out_of_range& e) {
+        qDebug() << e.what();
     }
     return QVariant();
 }
diff --git a/src/conversationsadapter.cpp b/src/conversationsadapter.cpp
index d53340017..038f135ac 100644
--- a/src/conversationsadapter.cpp
+++ b/src/conversationsadapter.cpp
@@ -91,9 +91,13 @@ ConversationsAdapter::selectConversation(const QString& accountId, const QString
             lrcInstance_->setSelectedConvId(convInfo.uid);
             accInfo.conversationModel->clearUnreadInteractions(convInfo.uid);
 
-            // Set contact filter (for conversation tab selection)
-            auto& contact = accInfo.contactModel->getContact(convInfo.participants.front());
-            setProperty("currentTypeFilter", QVariant::fromValue(contact.profileInfo.type));
+            try {
+                // Set contact filter (for conversation tab selection)
+                auto& contact = accInfo.contactModel->getContact(convInfo.participants.front());
+                setProperty("currentTypeFilter", QVariant::fromValue(contact.profileInfo.type));
+            } catch (const std::out_of_range& e) {
+                qDebug() << e.what();
+            }
         };
         if (convInfo.accountId != lrcInstance_->getCurrAccId()) {
             Utils::oneShotConnect(lrcInstance_,
diff --git a/src/moderatorlistmodel.cpp b/src/moderatorlistmodel.cpp
index 86c00b3c6..f64ecf927 100644
--- a/src/moderatorlistmodel.cpp
+++ b/src/moderatorlistmodel.cpp
@@ -50,22 +50,26 @@ ModeratorListModel::columnCount(const QModelIndex& parent) const
 QVariant
 ModeratorListModel::data(const QModelIndex& index, int role) const
 {
-    QStringList list = lrcInstance_->accountModel().getDefaultModerators(
-        lrcInstance_->getCurrAccId());
-    if (!index.isValid() || list.size() <= index.row()) {
-        return QVariant();
-    }
-    auto contactInfo = lrcInstance_->getCurrentAccountInfo().contactModel->getContact(
-        list.at(index.row()));
-
-    switch (role) {
-    case Role::ContactName: {
-        QString str = lrcInstance_->getCurrentAccountInfo().contactModel->bestNameForContact(
+    try {
+        QStringList list = lrcInstance_->accountModel().getDefaultModerators(
+                    lrcInstance_->getCurrAccId());
+        if (!index.isValid() || list.size() <= index.row()) {
+            return QVariant();
+        }
+        auto contactInfo = lrcInstance_->getCurrentAccountInfo().contactModel->getContact(
             list.at(index.row()));
-        return QVariant(str);
-    }
-    case Role::ContactID:
-        return QVariant(contactInfo.profileInfo.uri);
+
+        switch (role) {
+        case Role::ContactName: {
+            QString str = lrcInstance_->getCurrentAccountInfo().contactModel->
+                    bestNameForContact(list.at(index.row()));
+            return QVariant(str);
+        }
+        case Role::ContactID:
+            return QVariant(contactInfo.profileInfo.uri);
+        }
+    } catch (const std::exception& e) {
+        qDebug() << e.what();
     }
     return QVariant();
 }
diff --git a/src/settingsadapter.cpp b/src/settingsadapter.cpp
index 55429b7db..ea329887d 100644
--- a/src/settingsadapter.cpp
+++ b/src/settingsadapter.cpp
@@ -935,8 +935,12 @@ SettingsAdapter::unbanContact(int index)
     auto it = bannedContactList.begin();
     std::advance(it, index);
 
-    auto contactInfo = accountInfo.contactModel->getContact(*it);
-    accountInfo.contactModel->addContact(contactInfo);
+    try {
+        auto contactInfo = accountInfo.contactModel->getContact(*it);
+        accountInfo.contactModel->addContact(contactInfo);
+    } catch (const std::out_of_range& e) {
+        qDebug() << e.what();
+    }
 }
 
 void
diff --git a/src/settingsview/components/VideoSettings.qml b/src/settingsview/components/VideoSettings.qml
index 8680ae485..cfa38815b 100644
--- a/src/settingsview/components/VideoSettings.qml
+++ b/src/settingsview/components/VideoSettings.qml
@@ -96,14 +96,14 @@ ColumnLayout {
 
     function setFormatListForCurrentDevice() {
         var device = AVModel.getCurrentVideoCaptureDevice()
-        if (SettingsAdapter.get_DeviceCapabilitiesSize(device) === 0)
-            return
-
         try {
+            if (SettingsAdapter.get_DeviceCapabilitiesSize(device) === 0)
+                return
+
             resolutionComboBoxSetting.comboModel.reset()
             resolutionComboBoxSetting.setCurrentIndex(
                         resolutionComboBoxSetting.comboModel.getCurrentSettingIndex(), true)
-        } catch(err){ console.warn("Exception: " + err.message) }
+        } catch(err) { console.warn("Exception: " + err.message) }
     }
 
     function slotFormatCurrentIndexChanged(index, isResolutionIndex) {
diff --git a/src/utils.cpp b/src/utils.cpp
index 0edb4c2fc..bac7ab799 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -352,7 +352,8 @@ Utils::contactPhoto(LRCInstance* instance, const QString& contactUri, const QSiz
             auto avatarName = contactInfo.profileInfo.uri == bestName ? QString() : bestName;
             photo = Utils::fallbackAvatar("ring:" + contactInfo.profileInfo.uri, avatarName);
         }
-    } catch (...) {
+    } catch (const std::exception& e) {
+        qDebug() << e.what();
     }
     return Utils::scaleAndFrame(photo, size);
 }
@@ -506,7 +507,8 @@ Utils::profileType(const lrc::api::conversation::Info& conv,
     try {
         auto contact = model.owner.contactModel->getContact(conv.participants[0]);
         return contact.profileInfo.type;
-    } catch (...) {
+    } catch (const std::out_of_range& e) {
+        qDebug() << e.what();
         return lrc::api::profile::Type::INVALID;
     }
 }
@@ -539,12 +541,17 @@ Utils::isInteractionGenerated(const lrc::api::interaction::Type& type)
 bool
 Utils::isContactValid(const QString& contactUid, const lrc::api::ConversationModel& model)
 {
-    const auto contact = model.owner.contactModel->getContact(contactUid);
-    return (contact.profileInfo.type == lrc::api::profile::Type::PENDING
-            || contact.profileInfo.type == lrc::api::profile::Type::TEMPORARY
-            || contact.profileInfo.type == lrc::api::profile::Type::RING
-            || contact.profileInfo.type == lrc::api::profile::Type::SIP)
-           && !contact.profileInfo.uri.isEmpty();
+    try {
+        const auto contact = model.owner.contactModel->getContact(contactUid);
+        return (contact.profileInfo.type == lrc::api::profile::Type::PENDING
+                || contact.profileInfo.type == lrc::api::profile::Type::TEMPORARY
+                || contact.profileInfo.type == lrc::api::profile::Type::RING
+                || contact.profileInfo.type == lrc::api::profile::Type::SIP)
+               && !contact.profileInfo.uri.isEmpty();
+    } catch (const std::out_of_range& e) {
+        qDebug() << e.what();
+        return false;
+    }
 }
 
 bool
diff --git a/src/utilsadapter.cpp b/src/utilsadapter.cpp
index f885a7b0b..4ab6a6789 100644
--- a/src/utilsadapter.cpp
+++ b/src/utilsadapter.cpp
@@ -1,359 +1,364 @@
-/*!
- * Copyright (C) 2015-2020 by Savoir-faire Linux
- * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>
- * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
- * Author: Isa Nanic <isa.nanic@savoirfairelinux.com>
- * Author: Mingrui Zhang   <mingrui.zhang@savoirfairelinux.com>
- * Author: Aline Gondim Santos   <aline.gondimsantos@savoirfairelinux.com>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#include "utilsadapter.h"
-
-#include "globalsystemtray.h"
-#include "lrcinstance.h"
-#include "utils.h"
-#include "version.h"
-
-#include <QApplication>
-#include <QClipboard>
-#include <QFileInfo>
-
-UtilsAdapter::UtilsAdapter(QObject* parent, LRCInstance* instance)
-    : QmlAdapterBase(parent, instance)
-    , clipboard_(QApplication::clipboard())
-{}
-
-const QString
-UtilsAdapter::getProjectCredits()
-{
-    return Utils::getProjectCredits();
-}
-
-const QString
-UtilsAdapter::getVersionStr()
-{
-    return QString(VERSION_STRING);
-}
-
-void
-UtilsAdapter::setText(QString text)
-{
-    clipboard_->setText(text, QClipboard::Clipboard);
-}
-
-const QString
-UtilsAdapter::qStringFromFile(const QString& filename)
-{
-    return Utils::QByteArrayFromFile(filename);
-}
-
-const QString
-UtilsAdapter::getStyleSheet(const QString& name, const QString& source)
-{
-    auto simplifiedCSS = source.simplified().replace("'", "\"");
-    QString s = QString::fromLatin1("(function() {"
-                                    "    var node = document.createElement('style');"
-                                    "    node.id = '%1';"
-                                    "    node.innerHTML = '%2';"
-                                    "    document.head.appendChild(node);"
-                                    "})()")
-                    .arg(name)
-                    .arg(simplifiedCSS);
-    return s;
-}
-
-const QString
-UtilsAdapter::getCachePath()
-{
-    QDir dataDir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
-    dataDir.cdUp();
-    return dataDir.absolutePath() + "/jami";
-}
-bool
-UtilsAdapter::createStartupLink()
-{
-    return Utils::CreateStartupLink(L"Jami");
-}
-
-QString
-UtilsAdapter::GetRingtonePath()
-{
-    return Utils::GetRingtonePath();
-}
-
-bool
-UtilsAdapter::checkStartupLink()
-{
-    return Utils::CheckStartupLink(L"Jami");
-}
-
-const QString
-UtilsAdapter::getBestName(const QString& accountId, const QString& uid)
-{
-    const auto& conv = lrcInstance_->getConversationFromConvUid(uid);
-    if (!conv.participants.isEmpty())
-        return lrcInstance_->getAccountInfo(accountId).contactModel->bestNameForContact(
-            conv.participants[0]);
-    return QString();
-}
-
-const QString
-UtilsAdapter::getPeerUri(const QString& accountId, const QString& uid)
-{
-    auto* convModel = lrcInstance_->getAccountInfo(accountId).conversationModel.get();
-    const auto& convInfo = convModel->getConversationForUid(uid).value();
-    return convInfo.get().participants.front();
-}
-
-QString
-UtilsAdapter::getBestId(const QString& accountId)
-{
-    if (accountId.isEmpty())
-        return {};
-    return lrcInstance_->accountModel().bestIdForAccount(accountId);
-}
-
-const QString
-UtilsAdapter::getBestId(const QString& accountId, const QString& uid)
-{
-    const auto& conv = lrcInstance_->getConversationFromConvUid(uid);
-    if (!conv.participants.isEmpty())
-        return lrcInstance_->getAccountInfo(accountId).contactModel->bestIdForContact(
-            conv.participants[0]);
-    return QString();
-}
-
-int
-UtilsAdapter::getTotalUnreadMessages()
-{
-    int totalUnreadMessages {0};
-    if (lrcInstance_->getCurrentAccountInfo().profileInfo.type != lrc::api::profile::Type::SIP) {
-        auto* convModel = lrcInstance_->getCurrentConversationModel();
-        auto ringConversations = convModel->getFilteredConversations(lrc::api::profile::Type::RING,
-                                                                     false);
-        ringConversations.for_each(
-            [&totalUnreadMessages](const lrc::api::conversation::Info& conversation) {
-                totalUnreadMessages += conversation.unreadMessages;
-            });
-    }
-    return totalUnreadMessages;
-}
-
-int
-UtilsAdapter::getTotalPendingRequest()
-{
-    auto& accountInfo = lrcInstance_->getCurrentAccountInfo();
-    return accountInfo.contactModel->pendingRequestCount();
-}
-
-void
-UtilsAdapter::setConversationFilter(const QString& filter)
-{
-    lrcInstance_->getCurrentConversationModel()->setFilter(filter);
-}
-
-const QString
-UtilsAdapter::getCurrConvId()
-{
-    return lrcInstance_->getCurrentConvUid();
-}
-
-void
-UtilsAdapter::makePermanentCurrentConv()
-{
-    lrcInstance_->getCurrentConversationModel()->makePermanent(lrcInstance_->getCurrentConvUid());
-}
-
-const QStringList
-UtilsAdapter::getCurrAccList()
-{
-    return lrcInstance_->accountModel().getAccountList();
-}
-
-int
-UtilsAdapter::getAccountListSize()
-{
-    return getCurrAccList().size();
-}
-
-bool
-UtilsAdapter::hasCall(const QString& accountId)
-{
-    auto activeCalls = lrcInstance_->getActiveCalls();
-    for (const auto& callId : activeCalls) {
-        auto& accountInfo = lrcInstance_->accountModel().getAccountInfo(accountId);
-        if (accountInfo.callModel->hasCall(callId)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-const QString
-UtilsAdapter::getCallConvForAccount(const QString& accountId)
-{
-    // TODO: Currently returning first call, establish priority according to state?
-    for (const auto& callId : lrcInstance_->getActiveCalls()) {
-        auto& accountInfo = lrcInstance_->accountModel().getAccountInfo(accountId);
-        if (accountInfo.callModel->hasCall(callId)) {
-            return lrcInstance_->getConversationFromCallId(callId, accountId).uid;
-        }
-    }
-    return "";
-}
-
-const QString
-UtilsAdapter::getCallId(const QString& accountId, const QString& convUid)
-{
-    auto const& convInfo = lrcInstance_->getConversationFromConvUid(convUid, accountId);
-    if (convInfo.uid.isEmpty()) {
-        return {};
-    }
-
-    if (auto* call = lrcInstance_->getCallInfoForConversation(convInfo, false)) {
-        return call->id;
-    }
-
-    return {};
-}
-
-int
-UtilsAdapter::getCallStatus(const QString& callId)
-{
-    const auto callStatus = lrcInstance_->getCallInfo(callId, lrcInstance_->getCurrAccId());
-    return static_cast<int>(callStatus->status);
-}
-
-const QString
-UtilsAdapter::getCallStatusStr(int statusInt)
-{
-    const auto status = static_cast<lrc::api::call::Status>(statusInt);
-    return lrc::api::call::to_string(status);
-}
-
-// returns true if name is valid registered name
-bool
-UtilsAdapter::validateRegNameForm(const QString& regName)
-{
-    QRegularExpression regExp(" ");
-
-    if (regName.size() > 2 && !regName.contains(regExp)) {
-        return true;
-
-    } else {
-        return false;
-    }
-}
-
-QString
-UtilsAdapter::getStringUTF8(QString string)
-{
-    return string.toUtf8();
-}
-
-QString
-UtilsAdapter::getRecordQualityString(int value)
-{
-    return value ? QString::number(static_cast<float>(value) / 100, 'f', 1) + " Mbps" : "Default";
-}
-
-QString
-UtilsAdapter::getCurrentPath()
-{
-    return QDir::currentPath();
-}
-
-QString
-UtilsAdapter::stringSimplifier(QString input)
-{
-    return input.simplified();
-}
-
-QString
-UtilsAdapter::toNativeSeparators(QString inputDir)
-{
-    return QDir::toNativeSeparators(inputDir);
-}
-
-QString
-UtilsAdapter::toFileInfoName(QString inputFileName)
-{
-    QFileInfo fi(inputFileName);
-    return fi.fileName();
-}
-
-QString
-UtilsAdapter::toFileAbsolutepath(QString inputFileName)
-{
-    QFileInfo fi(inputFileName);
-    return fi.absolutePath();
-}
-
-QString
-UtilsAdapter::getAbsPath(QString path)
-{
-    // Note: this function is used on urls returned from qml-FileDialogs which
-    // contain 'file:///' for reasons we don't understand.
-    // TODO: this logic can be refactored into the JamiFileDialog component.
-#ifdef Q_OS_WIN
-    return path.replace(QRegExp("^file:\\/{2,3}"), "").replace("\n", "").replace("\r", "");
-#else
-    return path.replace(QRegExp("^file:\\/{2,3}"), "/").replace("\n", "").replace("\r", "");
-#endif
-}
-
-bool
-UtilsAdapter::checkShowPluginsButton(bool isCall)
-{
-    if (isCall)
-        return lrcInstance_->pluginModel().getPluginsEnabled()
-               && (lrcInstance_->pluginModel().getCallMediaHandlers().size() > 0);
-    else
-        return lrcInstance_->pluginModel().getPluginsEnabled()
-               && (lrcInstance_->pluginModel().getChatHandlers().size() > 0);
-}
-
-QString
-UtilsAdapter::fileName(const QString& path)
-{
-    QFileInfo fi(path);
-    return fi.fileName();
-}
-
-QString
-UtilsAdapter::getExt(const QString& path)
-{
-    QFileInfo fi(path);
-    return fi.completeSuffix();
-}
-
-bool
-UtilsAdapter::isImage(const QString& fileExt)
-{
-    return Utils::isImage(fileExt);
-}
-
-QString
-UtilsAdapter::humanFileSize(qint64 fileSize)
-{
-    return Utils::humanFileSize(fileSize);
-}
-
-void
-UtilsAdapter::setSystemTrayIconVisible(bool visible)
-{
-    GlobalSystemTray::instance().setVisible(visible);
-}
+/*!
+ * Copyright (C) 2015-2020 by Savoir-faire Linux
+ * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
+ * Author: Isa Nanic <isa.nanic@savoirfairelinux.com>
+ * Author: Mingrui Zhang   <mingrui.zhang@savoirfairelinux.com>
+ * Author: Aline Gondim Santos   <aline.gondimsantos@savoirfairelinux.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "utilsadapter.h"
+
+#include "globalsystemtray.h"
+#include "lrcinstance.h"
+#include "utils.h"
+#include "version.h"
+
+#include <QApplication>
+#include <QClipboard>
+#include <QFileInfo>
+
+UtilsAdapter::UtilsAdapter(QObject* parent, LRCInstance* instance)
+    : QmlAdapterBase(parent, instance)
+    , clipboard_(QApplication::clipboard())
+{}
+
+const QString
+UtilsAdapter::getProjectCredits()
+{
+    return Utils::getProjectCredits();
+}
+
+const QString
+UtilsAdapter::getVersionStr()
+{
+    return QString(VERSION_STRING);
+}
+
+void
+UtilsAdapter::setText(QString text)
+{
+    clipboard_->setText(text, QClipboard::Clipboard);
+}
+
+const QString
+UtilsAdapter::qStringFromFile(const QString& filename)
+{
+    return Utils::QByteArrayFromFile(filename);
+}
+
+const QString
+UtilsAdapter::getStyleSheet(const QString& name, const QString& source)
+{
+    auto simplifiedCSS = source.simplified().replace("'", "\"");
+    QString s = QString::fromLatin1("(function() {"
+                                    "    var node = document.createElement('style');"
+                                    "    node.id = '%1';"
+                                    "    node.innerHTML = '%2';"
+                                    "    document.head.appendChild(node);"
+                                    "})()")
+                    .arg(name)
+                    .arg(simplifiedCSS);
+    return s;
+}
+
+const QString
+UtilsAdapter::getCachePath()
+{
+    QDir dataDir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
+    dataDir.cdUp();
+    return dataDir.absolutePath() + "/jami";
+}
+bool
+UtilsAdapter::createStartupLink()
+{
+    return Utils::CreateStartupLink(L"Jami");
+}
+
+QString
+UtilsAdapter::GetRingtonePath()
+{
+    return Utils::GetRingtonePath();
+}
+
+bool
+UtilsAdapter::checkStartupLink()
+{
+    return Utils::CheckStartupLink(L"Jami");
+}
+
+const QString
+UtilsAdapter::getBestName(const QString& accountId, const QString& uid)
+{
+    const auto& conv = lrcInstance_->getConversationFromConvUid(uid);
+    if (!conv.participants.isEmpty())
+        return lrcInstance_->getAccountInfo(accountId).contactModel->bestNameForContact(
+            conv.participants[0]);
+    return QString();
+}
+
+const QString
+UtilsAdapter::getPeerUri(const QString& accountId, const QString& uid)
+{
+    try {
+        auto* convModel = lrcInstance_->getAccountInfo(accountId).conversationModel.get();
+        const auto& convInfo = convModel->getConversationForUid(uid).value();
+        return convInfo.get().participants.front();
+    } catch (const std::out_of_range& e) {
+        qDebug() << e.what();
+        return "";
+    }
+}
+
+QString
+UtilsAdapter::getBestId(const QString& accountId)
+{
+    if (accountId.isEmpty())
+        return {};
+    return lrcInstance_->accountModel().bestIdForAccount(accountId);
+}
+
+const QString
+UtilsAdapter::getBestId(const QString& accountId, const QString& uid)
+{
+    const auto& conv = lrcInstance_->getConversationFromConvUid(uid);
+    if (!conv.participants.isEmpty())
+        return lrcInstance_->getAccountInfo(accountId).contactModel->bestIdForContact(
+            conv.participants[0]);
+    return QString();
+}
+
+int
+UtilsAdapter::getTotalUnreadMessages()
+{
+    int totalUnreadMessages {0};
+    if (lrcInstance_->getCurrentAccountInfo().profileInfo.type != lrc::api::profile::Type::SIP) {
+        auto* convModel = lrcInstance_->getCurrentConversationModel();
+        auto ringConversations = convModel->getFilteredConversations(lrc::api::profile::Type::RING,
+                                                                     false);
+        ringConversations.for_each(
+            [&totalUnreadMessages](const lrc::api::conversation::Info& conversation) {
+                totalUnreadMessages += conversation.unreadMessages;
+            });
+    }
+    return totalUnreadMessages;
+}
+
+int
+UtilsAdapter::getTotalPendingRequest()
+{
+    auto& accountInfo = lrcInstance_->getCurrentAccountInfo();
+    return accountInfo.contactModel->pendingRequestCount();
+}
+
+void
+UtilsAdapter::setConversationFilter(const QString& filter)
+{
+    lrcInstance_->getCurrentConversationModel()->setFilter(filter);
+}
+
+const QString
+UtilsAdapter::getCurrConvId()
+{
+    return lrcInstance_->getCurrentConvUid();
+}
+
+void
+UtilsAdapter::makePermanentCurrentConv()
+{
+    lrcInstance_->getCurrentConversationModel()->makePermanent(lrcInstance_->getCurrentConvUid());
+}
+
+const QStringList
+UtilsAdapter::getCurrAccList()
+{
+    return lrcInstance_->accountModel().getAccountList();
+}
+
+int
+UtilsAdapter::getAccountListSize()
+{
+    return getCurrAccList().size();
+}
+
+bool
+UtilsAdapter::hasCall(const QString& accountId)
+{
+    auto activeCalls = lrcInstance_->getActiveCalls();
+    for (const auto& callId : activeCalls) {
+        auto& accountInfo = lrcInstance_->accountModel().getAccountInfo(accountId);
+        if (accountInfo.callModel->hasCall(callId)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+const QString
+UtilsAdapter::getCallConvForAccount(const QString& accountId)
+{
+    // TODO: Currently returning first call, establish priority according to state?
+    for (const auto& callId : lrcInstance_->getActiveCalls()) {
+        auto& accountInfo = lrcInstance_->accountModel().getAccountInfo(accountId);
+        if (accountInfo.callModel->hasCall(callId)) {
+            return lrcInstance_->getConversationFromCallId(callId, accountId).uid;
+        }
+    }
+    return "";
+}
+
+const QString
+UtilsAdapter::getCallId(const QString& accountId, const QString& convUid)
+{
+    auto const& convInfo = lrcInstance_->getConversationFromConvUid(convUid, accountId);
+    if (convInfo.uid.isEmpty()) {
+        return {};
+    }
+
+    if (auto* call = lrcInstance_->getCallInfoForConversation(convInfo, false)) {
+        return call->id;
+    }
+
+    return {};
+}
+
+int
+UtilsAdapter::getCallStatus(const QString& callId)
+{
+    const auto callStatus = lrcInstance_->getCallInfo(callId, lrcInstance_->getCurrAccId());
+    return static_cast<int>(callStatus->status);
+}
+
+const QString
+UtilsAdapter::getCallStatusStr(int statusInt)
+{
+    const auto status = static_cast<lrc::api::call::Status>(statusInt);
+    return lrc::api::call::to_string(status);
+}
+
+// returns true if name is valid registered name
+bool
+UtilsAdapter::validateRegNameForm(const QString& regName)
+{
+    QRegularExpression regExp(" ");
+
+    if (regName.size() > 2 && !regName.contains(regExp)) {
+        return true;
+
+    } else {
+        return false;
+    }
+}
+
+QString
+UtilsAdapter::getStringUTF8(QString string)
+{
+    return string.toUtf8();
+}
+
+QString
+UtilsAdapter::getRecordQualityString(int value)
+{
+    return value ? QString::number(static_cast<float>(value) / 100, 'f', 1) + " Mbps" : "Default";
+}
+
+QString
+UtilsAdapter::getCurrentPath()
+{
+    return QDir::currentPath();
+}
+
+QString
+UtilsAdapter::stringSimplifier(QString input)
+{
+    return input.simplified();
+}
+
+QString
+UtilsAdapter::toNativeSeparators(QString inputDir)
+{
+    return QDir::toNativeSeparators(inputDir);
+}
+
+QString
+UtilsAdapter::toFileInfoName(QString inputFileName)
+{
+    QFileInfo fi(inputFileName);
+    return fi.fileName();
+}
+
+QString
+UtilsAdapter::toFileAbsolutepath(QString inputFileName)
+{
+    QFileInfo fi(inputFileName);
+    return fi.absolutePath();
+}
+
+QString
+UtilsAdapter::getAbsPath(QString path)
+{
+    // Note: this function is used on urls returned from qml-FileDialogs which
+    // contain 'file:///' for reasons we don't understand.
+    // TODO: this logic can be refactored into the JamiFileDialog component.
+#ifdef Q_OS_WIN
+    return path.replace(QRegExp("^file:\\/{2,3}"), "").replace("\n", "").replace("\r", "");
+#else
+    return path.replace(QRegExp("^file:\\/{2,3}"), "/").replace("\n", "").replace("\r", "");
+#endif
+}
+
+bool
+UtilsAdapter::checkShowPluginsButton(bool isCall)
+{
+    if (isCall)
+        return lrcInstance_->pluginModel().getPluginsEnabled()
+               && (lrcInstance_->pluginModel().getCallMediaHandlers().size() > 0);
+    else
+        return lrcInstance_->pluginModel().getPluginsEnabled()
+               && (lrcInstance_->pluginModel().getChatHandlers().size() > 0);
+}
+
+QString
+UtilsAdapter::fileName(const QString& path)
+{
+    QFileInfo fi(path);
+    return fi.fileName();
+}
+
+QString
+UtilsAdapter::getExt(const QString& path)
+{
+    QFileInfo fi(path);
+    return fi.completeSuffix();
+}
+
+bool
+UtilsAdapter::isImage(const QString& fileExt)
+{
+    return Utils::isImage(fileExt);
+}
+
+QString
+UtilsAdapter::humanFileSize(qint64 fileSize)
+{
+    return Utils::humanFileSize(fileSize);
+}
+
+void
+UtilsAdapter::setSystemTrayIconVisible(bool visible)
+{
+    GlobalSystemTray::instance().setVisible(visible);
+}
-- 
GitLab