plugin: implement PATH preference

Change-Id: If86856104409c9c6f8402e0c9229481d18c5b84f
diff --git a/images/icons/insert_drive_file-24dp.svg b/images/icons/insert_drive_file-24dp.svg
new file mode 100644
index 0000000..91a279f
--- /dev/null
+++ b/images/icons/insert_drive_file-24dp.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px"><path d="M0 0h24v24H0z" fill="none"/><path d="M6 2c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6H6zm7 7V3.5L18.5 9H13z"/></svg>
\ No newline at end of file
diff --git a/jami-qt.pro b/jami-qt.pro
index 6ac5631..f7691b9 100644
--- a/jami-qt.pro
+++ b/jami-qt.pro
@@ -136,7 +136,7 @@
         ./src/qmladapterbase.h \
         ./src/avadapter.h \
         ./src/contactadapter.h \
-        ./src/mediahandleradapter.h \
+        ./src/pluginadapter.h \
         ./src/settingsadapter.h \
         ./src/deviceitemlistmodel.h \
         ./src/pluginitemlistmodel.h \
@@ -150,7 +150,6 @@
         ./src/videoinputdevicemodel.h \
         ./src/audiooutputdevicemodel.h \
         ./src/pluginlistpreferencemodel.h \
-        ./src/mediahandlerlistpreferencemodel.h \
         ./src/videoformatfpsmodel.h \
         ./src/videoformatresolutionmodel.h \
         ./src/audiomanagerlistmodel.h \
@@ -176,7 +175,7 @@
         ./src/previewrenderer.cpp \
         ./src/avadapter.cpp \
         ./src/contactadapter.cpp \
-        ./src/mediahandleradapter.cpp \
+        ./src/pluginadapter.cpp \
         ./src/settingsadapter.cpp \
         ./src/deviceitemlistmodel.cpp \
         ./src/pluginitemlistmodel.cpp \
@@ -190,7 +189,6 @@
         ./src/videoinputdevicemodel.cpp \
         ./src/audiooutputdevicemodel.cpp \
         ./src/pluginlistpreferencemodel.cpp \
-        ./src/mediahandlerlistpreferencemodel.cpp \
         ./src/videoformatfpsmodel.cpp \
         ./src/videoformatresolutionmodel.cpp \
         ./src/audiomanagerlistmodel.cpp \
diff --git a/resources.qrc b/resources.qrc
index 52770ec..808ae97 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -117,5 +117,6 @@
         <file>images/icons/drafts-24px.svg</file>
         <file>images/icons/person_add-24px.svg</file>
         <file>images/icons/router-24px.svg</file>
+        <file>images/icons/insert_drive_file-24dp.svg</file>
     </qresource>
 </RCC>
diff --git a/src/clientwrapper.h b/src/clientwrapper.h
index 790e6e8..f9a078a 100644
--- a/src/clientwrapper.h
+++ b/src/clientwrapper.h
@@ -26,7 +26,7 @@
 #include "bannedlistmodel.h"
 #include "calladapter.h"
 #include "contactadapter.h"
-#include "mediahandleradapter.h"
+#include "pluginadapter.h"
 #include "conversationsadapter.h"
 #include "deviceitemlistmodel.h"
 #include "pluginitemlistmodel.h"
diff --git a/src/commoncomponents/PreferenceItemDelegate.qml b/src/commoncomponents/PreferenceItemDelegate.qml
index 6a8f500..ab2b2b7 100644
--- a/src/commoncomponents/PreferenceItemDelegate.qml
+++ b/src/commoncomponents/PreferenceItemDelegate.qml
@@ -34,35 +34,35 @@
 
     enum Type {
         LIST,
-        USERLIST,
+        PATH,
         DEFAULT
     }
 
     property string preferenceName: ""
     property string preferenceSummary: ""
+    property string preferenceKey: ""
     property int preferenceType: -1
     property string preferenceCurrentValue: ""
     property string preferenceNewValue: ""
     property string pluginId: ""
+    property string currentPath: ""
+    property bool isImage: false
+    property var fileFilters: []
     property PluginListPreferenceModel pluginListPreferenceModel
 
     signal btnPreferenceClicked
-    signal preferenceAdded
 
     function getNewPreferenceValueSlot(index){
-        pluginListPreferenceModel.idx = index
-        preferenceNewValue = pluginListPreferenceModel.preferenceNewValue
         switch (preferenceType){
             case PreferenceItemDelegate.LIST:
+                pluginListPreferenceModel.idx = index
+                preferenceNewValue = pluginListPreferenceModel.preferenceNewValue
                 btnPreferenceClicked()
                 break
-            case PreferenceItemDelegate.USERLIST:
+            case PreferenceItemDelegate.PATH:
                 if(index == 0){
-                    preferenceFilePathDialog.pluginListPreferenceModel = pluginListPreferenceModel
                     preferenceFilePathDialog.title = qsTr("Select An Image to " + preferenceName)
-                    preferenceFilePathDialog.nameFilters = [qsTr("PNG Files") + " (*.png)", qsTr(
-                "All files") + " (*)"]
-                    preferenceFilePathDialog.preferenceKey = pluginListPreferenceModel.preferenceKey
+                    preferenceFilePathDialog.nameFilters = fileFilters
                     preferenceFilePathDialog.open()
                 }
                 else
@@ -76,36 +76,28 @@
     FileDialog {
         id: preferenceFilePathDialog
 
-        property string preferenceKey: ""
-        property PluginListPreferenceModel pluginListPreferenceModel
-
         title: qsTr("Please choose a file")
-        folder: StandardPaths.writableLocation(StandardPaths.DownloadLocation)
-
-        onRejected: preferenceAdded()
+        folder: "file://" + currentPath
 
         onAccepted: {
             var url = ClientWrapper.utilsAdaptor.getAbsPath(fileUrl.toString())
-            ClientWrapper.pluginModel.addValueToPreference(pluginId, preferenceKey, url)
-            pluginListPreferenceModel.populateLists()
-            pluginListPreferenceModel.getCurrentSettingIndex()
-            preferenceAdded()
+            preferenceNewValue = url
+            btnPreferenceClicked()
         }
     }
 
     RowLayout{
         anchors.fill: parent
 
-        Label{
-            visible: preferenceType === PreferenceItemDelegate.DEFAULT
-            Layout.fillWidth: true
-            Layout.alignment: Qt.AlingVCenter | Qt.AligntLeft
+        Label {
+            Layout.preferredWidth: root.width / 2
+            Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
             Layout.leftMargin: 8
 
-            font.pointSize: JamiTheme.settingsFontSize
-            font.kerning: true
-            font.bold: true
             text: preferenceName
+            font.pointSize: JamiTheme.settingsFontSize
+            ToolTip.visible: hovered
+            ToolTip.text: preferenceSummary
         }
 
         HoverableRadiusButton{
@@ -135,19 +127,6 @@
             }
         }
 
-        Label {
-            visible: preferenceType === PreferenceItemDelegate.LIST
-            Layout.preferredWidth: root.width / 2
-            Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
-            Layout.leftMargin: 8
-
-            text: preferenceName
-            font.pointSize: JamiTheme.settingsFontSize
-            ToolTip.visible: hovered
-            ToolTip.text: preferenceSummary
-        }
-
-
         SettingParaCombobox {
             id: listPreferenceComboBox
             visible: preferenceType === PreferenceItemDelegate.LIST
@@ -167,35 +146,29 @@
             }
         }
 
-        Label {
-            visible: preferenceType === PreferenceItemDelegate.USERLIST
-            Layout.preferredWidth: root.width / 2
-            Layout.leftMargin: 8
-            Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
-
-            text: preferenceName
-            font.pointSize: JamiTheme.settingsFontSize
-            ToolTip.visible: hovered
-            ToolTip.text: preferenceSummary
-        }
-
-
-        SettingParaCombobox {
-            id: userListPreferenceComboBox
-            visible: preferenceType === PreferenceItemDelegate.USERLIST
-            Layout.preferredWidth: root.width / 2 - 8
+        HoverableRadiusButton {
+            id: pathPreferenceButton
+            visible: preferenceType === PreferenceItemDelegate.PATH
+            Layout.preferredWidth: root.width / 2 - 16
+            Layout.maximumWidth: root.width / 2 - 16
             Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
-            Layout.rightMargin: 8
+            Layout.rightMargin: 30
+            Layout.preferredHeight: 30
 
-            font.pointSize: JamiTheme.settingsFontSize
-            font.kerning: true
+            radius: height / 2
 
-            model: pluginListPreferenceModel
-            currentIndex: pluginListPreferenceModel.getCurrentSettingIndex()
-            textRole: qsTr("PreferenceValue")
-            tooltipText: qsTr("Choose the preference")
-            onActivated: {
-                getNewPreferenceValueSlot(index)
+            icon.source: "qrc:/images/icons/round-folder-24px.svg"
+            icon.height: 24
+            icon.width: 24
+
+            toolTipText: qsTr("Press to choose an image file")
+            text: {
+                return ClientWrapper.utilsAdaptor.fileName(preferenceCurrentValue)
+            }
+            fontPointSize: JamiTheme.buttonFontSize
+
+            onClicked: {
+                getNewPreferenceValueSlot(0)
             }
         }
     }
diff --git a/src/mainview/components/MediaHandlerPicker.qml b/src/mainview/components/MediaHandlerPicker.qml
index c57fcf4..3030f44 100644
--- a/src/mainview/components/MediaHandlerPicker.qml
+++ b/src/mainview/components/MediaHandlerPicker.qml
@@ -27,7 +27,7 @@
     id: root
     function toggleMediaHandlerSlot(mediaHandlerId, isLoaded) {
         ClientWrapper.pluginModel.toggleCallMediaHandler(mediaHandlerId, !isLoaded)
-        mediahandlerPickerListView.model = MediaHandlerAdapter.getMediaHandlerSelectableModel()
+        mediahandlerPickerListView.model = PluginAdapter.getMediaHandlerSelectableModel()
     }
 
     width: 350
@@ -96,7 +96,7 @@
                     Layout.preferredWidth: mediahandlerPickerPopupRect.width
                     Layout.preferredHeight: 200
 
-                    model: MediaHandlerAdapter.getMediaHandlerSelectableModel()
+                    model: PluginAdapter.getMediaHandlerSelectableModel()
 
                     clip: true
 
@@ -119,7 +119,7 @@
                         onOpenPreferences: {
                             mediahandlerPreferencePickerListView.pluginId = pluginId
                             mediahandlerPreferencePickerListView.mediaHandlerName = mediaHandlerName
-                            mediahandlerPreferencePickerListView.model = MediaHandlerAdapter.getMediaHandlerPreferencesModel(pluginId, mediaHandlerName)
+                            mediahandlerPreferencePickerListView.model = PluginAdapter.getPluginPreferencesModel(pluginId, mediaHandlerName)
                             stack.currentIndex = 1
                         }
                     }
@@ -204,20 +204,24 @@
                     property string pluginId: ""
                     property string mediaHandlerName: ""
 
-                    model: MediaHandlerAdapter.getMediaHandlerPreferencesModel(pluginId, mediaHandlerName)
+                    model: PluginAdapter.getPluginPreferencesModel(pluginId, mediaHandlerName)
 
                     clip: true
 
                     delegate: PreferenceItemDelegate {
                         id: mediaHandlerPreferenceDelegate
                         width: mediahandlerPreferencePickerListView.width
-                        height: 50
+                        height: childrenRect.height
 
                         preferenceName: PreferenceName
                         preferenceSummary: PreferenceSummary
                         preferenceType: PreferenceType
                         preferenceCurrentValue: PreferenceCurrentValue
                         pluginId: PluginId
+                        currentPath: CurrentPath
+                        preferenceKey : PreferenceKey
+                        fileFilters: FileFilters
+                        isImage: IsImage
                         pluginListPreferenceModel: PluginListPreferenceModel{
                             id: pluginListPreferenceModel
                             preferenceKey : PreferenceKey
@@ -227,13 +231,9 @@
                         onClicked:  mediahandlerPreferencePickerListView.currentIndex = index
 
                         onBtnPreferenceClicked: {
-                            ClientWrapper.pluginModel.setPluginPreference(pluginListPreferenceModel.pluginId,
-                                                                            pluginListPreferenceModel.preferenceKey,
-                                                                            pluginListPreferenceModel.preferenceNewValue)
-                            mediahandlerPreferencePickerListView.model = MediaHandlerAdapter.getMediaHandlerPreferencesModel(pluginId, mediahandlerPreferencePickerListView.mediaHandlerName)
+                            ClientWrapper.pluginModel.setPluginPreference(pluginId, preferenceKey, preferenceNewValue)
+                            mediahandlerPreferencePickerListView.model = PluginAdapter.getPluginPreferencesModel(pluginId, mediahandlerPreferencePickerListView.mediaHandlerName)
                         }
-
-                        onPreferenceAdded: mediahandlerPreferencePickerListView.model = MediaHandlerAdapter.getMediaHandlerPreferencesModel(pluginId, mediahandlerPreferencePickerListView.mediaHandlerName)
                     }
 
                     ScrollIndicator.vertical: ScrollIndicator {}
@@ -246,7 +246,7 @@
 
     onAboutToShow: {
         // Reset the model on each show.
-        mediahandlerPickerListView.model = MediaHandlerAdapter.getMediaHandlerSelectableModel()
+        mediahandlerPickerListView.model = PluginAdapter.getMediaHandlerSelectableModel()
     }
 
     background: Rectangle {
diff --git a/src/mediahandleradapter.cpp b/src/mediahandleradapter.cpp
deleted file mode 100644
index d35117d..0000000
--- a/src/mediahandleradapter.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * Copyright (C) 2020 by Savoir-faire Linux
- * 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 "mediahandleradapter.h"
-
-#include "lrcinstance.h"
-
-MediaHandlerAdapter::MediaHandlerAdapter(QObject* parent)
-    : QmlAdapterBase(parent)
-{}
-
-QVariant
-MediaHandlerAdapter::getMediaHandlerSelectableModel()
-{
-    /*
-     * Called from qml every time contact picker refreshes.
-     */
-    mediaHandlerListModel_.reset(new MediaHandlerItemListModel(this));
-
-    return QVariant::fromValue(mediaHandlerListModel_.get());
-}
-
-QVariant
-MediaHandlerAdapter::getMediaHandlerPreferencesModel(QString pluginId, QString mediaHandlerName)
-{
-    /*
-     * Called from qml every time contact picker refreshes.
-     */
-    mediaHandlerPreferenceItemListModel_.reset(new PreferenceItemListModel(this));
-    mediaHandlerPreferenceItemListModel_->setMediaHandlerName(mediaHandlerName);
-    mediaHandlerPreferenceItemListModel_->setPluginId(pluginId);
-
-    return QVariant::fromValue(mediaHandlerPreferenceItemListModel_.get());
-}
-
-QVariant
-MediaHandlerAdapter::getMediaHandlerPreferencesSelectableModel(QString pluginId)
-{
-    /*
-     * Called from qml every time contact picker refreshes.
-     */
-    mediaHandlerListPreferenceModel_.reset(new MediaHandlerListPreferenceModel(this));
-    mediaHandlerListPreferenceModel_->setPluginId(pluginId);
-
-    return QVariant::fromValue(mediaHandlerListPreferenceModel_.get());
-}
diff --git a/src/mediahandlerlistpreferencemodel.cpp b/src/mediahandlerlistpreferencemodel.cpp
deleted file mode 100644
index dde3c60..0000000
--- a/src/mediahandlerlistpreferencemodel.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-/**
- * Copyright (C) 2019-2020 by Savoir-faire Linux
- * 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 "mediahandlerlistpreferencemodel.h"
-#include <regex>
-
-MediaHandlerListPreferenceModel::MediaHandlerListPreferenceModel(QObject* parent)
-    : QAbstractListModel(parent)
-{}
-
-MediaHandlerListPreferenceModel::~MediaHandlerListPreferenceModel() {}
-
-void
-MediaHandlerListPreferenceModel::populateLists()
-{
-    preferenceValuesList_.clear();
-    preferenceList_.clear();
-    const auto preferences = LRCInstance::pluginModel().getPluginPreferences(pluginId_);
-    for (const auto& preference : preferences) {
-        if (preference["key"] == preferenceKey_) {
-            auto entries = preference["entries"];
-            auto entriesValues = preference["entryValues"];
-            std::string entry = entries.toStdString();
-            std::string entryValues = entriesValues.toStdString();
-            std::string delimiter = ",";
-
-            size_t pos = 0;
-            std::string token;
-            while ((pos = entry.find(delimiter)) != std::string::npos) {
-                preferenceList_.emplace_back(entry.substr(0, pos));
-
-                entry.erase(0, pos + delimiter.length());
-            }
-            preferenceList_.emplace_back(entry.substr(0, pos));
-            while ((pos = entryValues.find(delimiter)) != std::string::npos) {
-                preferenceValuesList_.emplace_back(entryValues.substr(0, pos));
-
-                entryValues.erase(0, pos + delimiter.length());
-            }
-            preferenceValuesList_.emplace_back(entryValues.substr(0, pos));
-        }
-    }
-    getCurrentSettingIndex();
-}
-
-int
-MediaHandlerListPreferenceModel::rowCount(const QModelIndex& parent) const
-{
-    if (!parent.isValid()) {
-        /// Count
-        return preferenceList_.size();
-    }
-    /// A valid QModelIndex returns 0 as no entry has sub-elements.
-    return 0;
-}
-
-int
-MediaHandlerListPreferenceModel::columnCount(const QModelIndex& parent) const
-{
-    Q_UNUSED(parent);
-    /// Only need one column.
-    return 1;
-}
-
-QVariant
-MediaHandlerListPreferenceModel::data(const QModelIndex& index, int role) const
-{
-    if (!index.isValid() || preferenceList_.size() <= index.row()) {
-        return QVariant();
-    }
-
-    switch (role) {
-    case Role::PreferenceValue:
-        return QVariant(QString::fromStdString(preferenceList_.at(index.row())));
-    case Role::PreferenceEntryValue:
-        return QVariant(QString::fromStdString(preferenceValuesList_.at(index.row())));
-    }
-    return QVariant();
-}
-
-QHash<int, QByteArray>
-MediaHandlerListPreferenceModel::roleNames() const
-{
-    QHash<int, QByteArray> roles;
-    roles[PreferenceValue] = "PreferenceValue";
-    roles[PreferenceEntryValue] = "PreferenceEntryValue";
-    return roles;
-}
-
-QModelIndex
-MediaHandlerListPreferenceModel::index(int row, int column, const QModelIndex& parent) const
-{
-    Q_UNUSED(parent);
-    if (column != 0) {
-        return QModelIndex();
-    }
-
-    if (row >= 0 && row < rowCount()) {
-        return createIndex(row, column);
-    }
-    return QModelIndex();
-}
-
-QModelIndex
-MediaHandlerListPreferenceModel::parent(const QModelIndex& child) const
-{
-    Q_UNUSED(child);
-    return QModelIndex();
-}
-
-Qt::ItemFlags
-MediaHandlerListPreferenceModel::flags(const QModelIndex& index) const
-{
-    auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
-    if (!index.isValid()) {
-        return QAbstractItemModel::flags(index);
-    }
-    return flags;
-}
-
-void
-MediaHandlerListPreferenceModel::reset()
-{
-    beginResetModel();
-    endResetModel();
-}
-
-int
-MediaHandlerListPreferenceModel::getCurrentSettingIndex()
-{
-    auto resultList = match(index(0, 0), PreferenceEntryValue, preferenceCurrentValue());
-
-    int resultRowIndex = 0;
-    if (resultList.size() > 0) {
-        resultRowIndex = resultList[0].row();
-    }
-
-    return resultRowIndex;
-}
diff --git a/src/mediahandlerlistpreferencemodel.h b/src/mediahandlerlistpreferencemodel.h
deleted file mode 100644
index 30ff594..0000000
--- a/src/mediahandlerlistpreferencemodel.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * Copyright (C) 2020 by Savoir-faire Linux
- * 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/>.
- */
-
-#pragma once
-
-#include <QAbstractItemModel>
-
-#include "api/pluginmodel.h"
-
-#include "lrcinstance.h"
-
-class MediaHandlerListPreferenceModel : public QAbstractListModel
-{
-    Q_OBJECT
-    Q_PROPERTY(QString pluginId READ pluginId WRITE setPluginId)
-    Q_PROPERTY(QString preferenceKey READ preferenceKey WRITE setPreferenceKey)
-    Q_PROPERTY(QString preferenceNewValue READ preferenceNewValue WRITE setPreferenceNewValue)
-    Q_PROPERTY(int idx READ idx WRITE setIdx)
-    Q_PROPERTY(int optSize READ optSize)
-public:
-    enum Role { PreferenceValue = Qt::UserRole + 1, PreferenceEntryValue };
-    Q_ENUM(Role)
-
-    explicit MediaHandlerListPreferenceModel(QObject* parent = 0);
-    ~MediaHandlerListPreferenceModel();
-
-    /*
-     * QAbstractListModel override.
-     */
-    int rowCount(const QModelIndex& parent = QModelIndex()) const override;
-    int columnCount(const QModelIndex& parent) const override;
-    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
-    /*
-     * Override role name as access point in qml.
-     */
-    QHash<int, QByteArray> roleNames() const override;
-    QModelIndex index(int row, int column = 0, const QModelIndex& parent = QModelIndex()) const;
-    QModelIndex parent(const QModelIndex& child) const;
-    Qt::ItemFlags flags(const QModelIndex& index) const;
-
-    /*
-     * This function is to reset the model when there's new account added.
-     */
-    Q_INVOKABLE void reset();
-    /*
-     * This function is to get the current preference value
-     */
-    Q_INVOKABLE int getCurrentSettingIndex();
-
-    Q_INVOKABLE void populateLists();
-
-    void setPreferenceNewValue(const QString preferenceNewValue)
-    {
-        preferenceNewValue_ = preferenceNewValue;
-    }
-    void setPreferenceKey(const QString preferenceKey) { preferenceKey_ = preferenceKey; }
-    void setPluginId(const QString pluginId)
-    {
-        pluginId_ = pluginId;
-        populateLists();
-    }
-
-    void setIdx(const int index) { idx_ = index; }
-
-    int idx() { return idx_; }
-    QString preferenceCurrentValue()
-    {
-        return LRCInstance::pluginModel().getPluginPreferencesValues(pluginId_)[preferenceKey_];
-    }
-
-    QString preferenceNewValue()
-    {
-        preferenceNewValue_ = QString::fromStdString(preferenceValuesList_[idx_]);
-        return preferenceNewValue_;
-    }
-    QString preferenceKey() { return preferenceKey_; }
-    QString pluginId() { return pluginId_; }
-    int optSize() { return preferenceValuesList_.size(); }
-
-private:
-    QString pluginId_ = "";
-    QString preferenceKey_ = "";
-    QString preferenceNewValue_ = "";
-    std::vector<std::string> preferenceValuesList_;
-    std::vector<std::string> preferenceList_;
-    int idx_ = 0;
-};
diff --git a/src/pluginadapter.cpp b/src/pluginadapter.cpp
new file mode 100644
index 0000000..57b5d8b
--- /dev/null
+++ b/src/pluginadapter.cpp
@@ -0,0 +1,49 @@
+/*!
+ * Copyright (C) 2020 by Savoir-faire Linux
+ * 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 "pluginadapter.h"
+
+#include "lrcinstance.h"
+
+PluginAdapter::PluginAdapter(QObject* parent)
+    : QmlAdapterBase(parent)
+{}
+
+QVariant
+PluginAdapter::getMediaHandlerSelectableModel()
+{
+    mediaHandlerListModel_.reset(new MediaHandlerItemListModel(this));
+    return QVariant::fromValue(mediaHandlerListModel_.get());
+}
+
+QVariant
+PluginAdapter::getPluginSelectableModel()
+{
+    pluginItemListModel_.reset(new PluginItemListModel(this));
+    return QVariant::fromValue(pluginItemListModel_.get());
+}
+
+QVariant
+PluginAdapter::getPluginPreferencesModel(const QString& pluginId, const QString& mediaHandlerName)
+{
+    preferenceItemListModel_.reset(new PreferenceItemListModel(this));
+    preferenceItemListModel_->setMediaHandlerName(mediaHandlerName);
+    preferenceItemListModel_->setPluginId(pluginId);
+
+    return QVariant::fromValue(preferenceItemListModel_.get());
+}
diff --git a/src/mediahandleradapter.h b/src/pluginadapter.h
similarity index 67%
rename from src/mediahandleradapter.h
rename to src/pluginadapter.h
index 57837a6..814fcbb 100644
--- a/src/mediahandleradapter.h
+++ b/src/pluginadapter.h
@@ -19,31 +19,32 @@
 #pragma once
 
 #include "qmladapterbase.h"
+#include "pluginitemlistmodel.h"
 #include "mediahandleritemlistmodel.h"
-#include "mediahandlerlistpreferencemodel.h"
+#include "pluginlistpreferencemodel.h"
 #include "preferenceitemlistmodel.h"
 
 #include <QObject>
 #include <QSortFilterProxyModel>
 #include <QString>
 
-class MediaHandlerAdapter final : public QmlAdapterBase
+class PluginAdapter final : public QmlAdapterBase
 {
     Q_OBJECT
 public:
-    explicit MediaHandlerAdapter(QObject* parent = nullptr);
-    ~MediaHandlerAdapter() = default;
+    explicit PluginAdapter(QObject* parent = nullptr);
+    ~PluginAdapter() = default;
 
 protected:
     void safeInit() override {};
 
     Q_INVOKABLE QVariant getMediaHandlerSelectableModel();
-    Q_INVOKABLE QVariant getMediaHandlerPreferencesModel(QString pluginId, QString mediaHandlerName);
-    Q_INVOKABLE QVariant getMediaHandlerPreferencesSelectableModel(QString pluginId);
+    Q_INVOKABLE QVariant getPluginSelectableModel();
+    Q_INVOKABLE QVariant getPluginPreferencesModel(const QString& pluginId,
+                                                   const QString& mediaHandlerName = "");
 
 private:
     std::unique_ptr<MediaHandlerItemListModel> mediaHandlerListModel_;
-    std::unique_ptr<PreferenceItemListModel> mediaHandlerPreferenceItemListModel_;
-    std::unique_ptr<MediaHandlerListPreferenceModel> mediaHandlerListPreferenceModel_;
-
+    std::unique_ptr<PreferenceItemListModel> preferenceItemListModel_;
+    std::unique_ptr<PluginItemListModel> pluginItemListModel_;
 };
diff --git a/src/pluginlistpreferencemodel.cpp b/src/pluginlistpreferencemodel.cpp
index 8e76a27..9f54fb3 100644
--- a/src/pluginlistpreferencemodel.cpp
+++ b/src/pluginlistpreferencemodel.cpp
@@ -33,7 +33,9 @@
     const auto preferences = LRCInstance::pluginModel().getPluginPreferences(pluginId_);
     for (const auto& preference : preferences) {
         if (preference["key"] == preferenceKey_) {
-            preferenceList_ = preference["entries"].split(",");
+            if (preference.find("entries") != preference.end()
+                && preference.find("entryValues") != preference.end())
+                preferenceList_ = preference["entries"].split(",");
             preferenceValuesList_ = preference["entryValues"].split(",");
             break;
         }
diff --git a/src/preferenceitemlistmodel.cpp b/src/preferenceitemlistmodel.cpp
index 7742ff0..226e665 100644
--- a/src/preferenceitemlistmodel.cpp
+++ b/src/preferenceitemlistmodel.cpp
@@ -17,10 +17,11 @@
  */
 
 #include "preferenceitemlistmodel.h"
+#include "utils.h"
 #include <map>
 
 std::map<QString, int> mapType {{QString("List"), PreferenceItemListModel::Type::LIST},
-                                {QString("UserList"), PreferenceItemListModel::Type::USERLIST}};
+                                {QString("Path"), PreferenceItemListModel::Type::PATH}};
 
 PreferenceItemListModel::PreferenceItemListModel(QObject* parent)
     : QAbstractListModel(parent)
@@ -55,14 +56,27 @@
     }
 
     auto details = preferenceList_.at(index.row());
-    int type = Type::DEFAULT;
-    auto it = mapType.find(details["type"]);
-    if (it != mapType.end()) {
-        type = mapType[details["type"]];
-    }
     QString preferenceCurrent = LRCInstance::pluginModel().getPluginPreferencesValues(
         pluginId_)[details["key"]];
 
+    int type = Type::DEFAULT;
+    QString currentPath = "";
+    QStringList acceptedFiles = {};
+    bool checkImage = false;
+    auto it = mapType.find(details["type"]);
+    if (it != mapType.end()) {
+        type = mapType[details["type"]];
+        if (type == Type::PATH) {
+            currentPath = preferenceCurrent;
+            currentPath.truncate(preferenceCurrent.lastIndexOf("/"));
+            QStringList mimeTypeList = details["mimeType"].split(',');
+            for (auto& mimeType : mimeTypeList) {
+                QString fileExt = mimeType.mid(mimeType.lastIndexOf("/") + 1);
+                acceptedFiles.append((fileExt.toUpper() + " Files") + " (*." + fileExt + ")");
+                checkImage = UtilsAdapter().isImage(fileExt);
+            }
+        }
+    }
     switch (role) {
     case Role::PreferenceKey:
         return QVariant(details["key"]);
@@ -76,6 +90,12 @@
         return QVariant(pluginId_);
     case Role::PreferenceCurrentValue:
         return QVariant(preferenceCurrent);
+    case Role::CurrentPath:
+        return QVariant(currentPath);
+    case Role::FileFilters:
+        return QVariant(acceptedFiles);
+    case Role::IsImage:
+        return QVariant(checkImage);
     }
     return QVariant();
 }
@@ -90,6 +110,9 @@
     roles[PreferenceType] = "PreferenceType";
     roles[PluginId] = "PluginId";
     roles[PreferenceCurrentValue] = "PreferenceCurrentValue";
+    roles[CurrentPath] = "CurrentPath";
+    roles[FileFilters] = "FileFilters";
+    roles[IsImage] = "IsImage";
     return roles;
 }
 
@@ -167,23 +190,10 @@
     } else {
         auto preferences = LRCInstance::pluginModel().getPluginPreferences(pluginId_);
         for (auto& preference : preferences) {
-            std::string scope = preference["scope"].toStdString();
-            std::string delimiter = ",";
-
-            size_t pos = 0;
-            std::string token;
-            while ((pos = scope.find(delimiter)) != std::string::npos) {
-                token = scope.substr(0, pos);
-                if (token == mediaHandlerName_.toStdString()) {
-                    preferenceList_.push_back(preference);
-                    break;
-                }
-                scope.erase(0, pos + delimiter.length());
-            }
-            token = scope.substr(0, pos);
-            if (token == mediaHandlerName_.toStdString())
+            QStringList scopeList = preference["scope"].split(",");
+            if (scopeList.contains(mediaHandlerName_))
                 preferenceList_.push_back(preference);
         }
         return preferenceList_.size();
     }
-}
\ No newline at end of file
+}
diff --git a/src/preferenceitemlistmodel.h b/src/preferenceitemlistmodel.h
index 8514728..2bed54e 100644
--- a/src/preferenceitemlistmodel.h
+++ b/src/preferenceitemlistmodel.h
@@ -38,12 +38,15 @@
         PreferenceSummary,
         PreferenceType,
         PluginId,
-        PreferenceCurrentValue
+        PreferenceCurrentValue,
+        CurrentPath,
+        FileFilters,
+        IsImage
     };
 
     typedef enum {
         LIST,
-        USERLIST,
+        PATH,
         DEFAULT,
     } Type;
 
diff --git a/src/qmlregister.cpp b/src/qmlregister.cpp
index 02694a6..902e5e7 100644
--- a/src/qmlregister.cpp
+++ b/src/qmlregister.cpp
@@ -32,9 +32,8 @@
 #include "conversationsadapter.h"

 #include "deviceitemlistmodel.h"

 #include "distantrenderer.h"

-#include "mediahandleradapter.h"

+#include "pluginadapter.h"

 #include "mediahandleritemlistmodel.h"

-#include "mediahandlerlistpreferencemodel.h"

 #include "messagesadapter.h"

 #include "namedirectory.h"

 #include "preferenceitemlistmodel.h"

@@ -117,7 +116,6 @@
     QML_REGISTERTYPE(VideoFormatResolutionModel, 1, 0);

     QML_REGISTERTYPE(VideoFormatFpsModel, 1, 0);

     QML_REGISTERTYPE(PluginListPreferenceModel, 1, 0);

-    QML_REGISTERTYPE(MediaHandlerListPreferenceModel, 1, 0);

 

     /*

      * Register QQuickItem type.

@@ -141,7 +139,7 @@
     QML_REGISTERSINGLETONTYPE("net.jami.Models", ConversationsAdapter, 1, 0);

     QML_REGISTERSINGLETONTYPE("net.jami.Models", AvAdapter, 1, 0);

     QML_REGISTERSINGLETONTYPE("net.jami.Models", ContactAdapter, 1, 0);

-    QML_REGISTERSINGLETONTYPE("net.jami.Models", MediaHandlerAdapter, 1, 0);

+    QML_REGISTERSINGLETONTYPE("net.jami.Models", PluginAdapter, 1, 0);

     QML_REGISTERSINGLETONTYPE("net.jami.Models", ClientWrapper, 1, 0);

 

 

diff --git a/src/settingsview/components/PluginItemDelegate.qml b/src/settingsview/components/PluginItemDelegate.qml
index ce8f736..c9e6a5c 100644
--- a/src/settingsview/components/PluginItemDelegate.qml
+++ b/src/settingsview/components/PluginItemDelegate.qml
@@ -120,7 +120,7 @@
             }
 
             ToolTip.visible: hovered
-            ToolTip.text: qsTr("Show preferences")
+            ToolTip.text: qsTr("Show/Hide preferences")
 
             onClicked: btnPreferencesPluginClicked()
         }
diff --git a/src/settingsview/components/PluginListPreferencesView.qml b/src/settingsview/components/PluginListPreferencesView.qml
index 6e3f584..9d0eb1c 100644
--- a/src/settingsview/components/PluginListPreferencesView.qml
+++ b/src/settingsview/components/PluginListPreferencesView.qml
@@ -32,12 +32,10 @@
 
     enum Type {
         LIST,
-        USERLIST,
+        PATH,
         DEFAULT
     }
 
-    signal updatePluginList
-
     property string pluginName: ""
     property string pluginIcon: ""
     property string pluginId: ""
@@ -45,14 +43,6 @@
 
     visible: false
 
-    function updatePreferenceListDisplayed(){
-        // settings
-        preferenceItemListModel.pluginId = pluginId
-        preferenceItemListModel.reset()
-        var size = 50 * preferenceItemListModel.preferencesCount
-        pluginPreferenceView.height = size
-    }
-
     function resetPluginSlot(){
         resetPluginMessageBox.open()
     }
@@ -65,8 +55,7 @@
         } else {
             ClientWrapper.pluginModel.resetPluginPreferencesValues(pluginId)
         }
-        updatePluginList()
-        updatePreferenceListDisplayed()
+        pluginPreferenceView.model = PluginAdapter.getPluginPreferencesModel(pluginId)
     }
 
     function uninstallPluginSlot(){
@@ -75,7 +64,6 @@
 
     function uninstallPlugin(){
         ClientWrapper.pluginModel.uninstallPlugin(pluginId)
-        updatePluginList()
     }
 
     function setPreference(pluginId, preferenceKey, preferenceNewValue)
@@ -115,10 +103,6 @@
         onAccepted: resetPlugin()
     }
 
-    PreferenceItemListModel {
-        id: preferenceItemListModel
-    }
-
     ColumnLayout {
         anchors.left: root.left
         anchors.right: root.right
@@ -195,19 +179,23 @@
             Layout.minimumHeight: 0
             Layout.preferredHeight: childrenRect.height + 30
 
-            model: preferenceItemListModel
+            model: PluginAdapter.getPluginPreferencesModel(pluginId)
 
             delegate: PreferenceItemDelegate{
                 id: preferenceItemDelegate
 
                 width: pluginPreferenceView.width
-                height: 50
+                height: childrenRect.height
 
                 preferenceName: PreferenceName
                 preferenceSummary: PreferenceSummary
                 preferenceType: PreferenceType
                 preferenceCurrentValue: PreferenceCurrentValue
                 pluginId: PluginId
+                currentPath: CurrentPath
+                preferenceKey: PreferenceKey
+                fileFilters: FileFilters
+                isImage: IsImage
                 pluginListPreferenceModel: PluginListPreferenceModel{
                     id: pluginListPreferenceModel
                     preferenceKey : PreferenceKey
@@ -218,12 +206,9 @@
                     pluginPreferenceView.currentIndex = index
                 }
                 onBtnPreferenceClicked: {
-                    setPreference(pluginListPreferenceModel.pluginId,
-                                  pluginListPreferenceModel.preferenceKey,
-                                  pluginListPreferenceModel.preferenceNewValue)
-                    updatePreferenceListDisplayed()
+                    setPreference(pluginId, preferenceKey, preferenceNewValue)
+                    pluginPreferenceView.model = PluginAdapter.getPluginPreferencesModel(pluginId)
                 }
-                onPreferenceAdded: preferenceItemListModel.reset()
             }
         }
     }
diff --git a/src/settingsview/components/PluginListSettingsView.qml b/src/settingsview/components/PluginListSettingsView.qml
index 389ab4f..3d1c1f1 100644
--- a/src/settingsview/components/PluginListSettingsView.qml
+++ b/src/settingsview/components/PluginListSettingsView.qml
@@ -33,13 +33,6 @@
 
     visible: false
 
-    function updatePluginListDisplayed() {
-        // settings
-        pluginItemListModel.reset()
-        var size = 50 * pluginItemListModel.pluginsCount
-        pluginListView.height = size + 15
-    }
-
     function openPluginFileSlot(){
         pluginPathDialog.open()
     }
@@ -52,7 +45,6 @@
             loaded = ClientWrapper.pluginModel.loadPlugin(pluginId)
         if(pluginListPreferencesView.pluginId === pluginId)
             pluginListPreferencesView.isLoaded = loaded
-        updatePluginListDisplayed()
     }
 
     function openPreferencesPluginSlot(pluginName, pluginIcon, pluginId, isLoaded){
@@ -67,13 +59,11 @@
             pluginListPreferencesView.pluginId = pluginId
             pluginListPreferencesView.isLoaded = isLoaded
         }
-        pluginListPreferencesView.updatePreferenceListDisplayed()
     }
 
     function hidePreferences(){
         pluginListPreferencesView.pluginId = ""
         pluginListPreferencesView.visible = false
-        pluginListPreferencesView.updatePreferenceListDisplayed()
     }
 
     JamiFileDialog {
@@ -97,7 +87,6 @@
         onAccepted: {
             var url = ClientWrapper.utilsAdaptor.getAbsPath(file.toString())
             ClientWrapper.pluginModel.installPlugin(url, true)
-            updatePluginListDisplayed()
         }
     }
 
@@ -122,8 +111,8 @@
             id: installButton
 
             Layout.alignment: Qt.AlignCenter
-            Layout.preferredWidth: preferredWidth
-            Layout.preferredHeight: preferredHeight
+            Layout.preferredWidth: JamiTheme.preferredFieldWidth
+            Layout.preferredHeight: JamiTheme.preferredFieldHeight
 
             color: JamiTheme.buttonTintedBlack
             hoveredColor: JamiTheme.buttonTintedBlackHovered
@@ -149,9 +138,7 @@
             Layout.minimumHeight: 0
             Layout.preferredHeight: childrenRect.height
 
-            model: PluginItemListModel{
-                id: pluginItemListModel
-            }
+            model: PluginAdapter.getPluginSelectableModel()
 
             delegate: PluginItemDelegate{
                 id: pluginItemDelegate
diff --git a/src/settingsview/components/PluginSettingsPage.qml b/src/settingsview/components/PluginSettingsPage.qml
index 3cff938..156706d 100644
--- a/src/settingsview/components/PluginSettingsPage.qml
+++ b/src/settingsview/components/PluginSettingsPage.qml
@@ -33,9 +33,6 @@
         // settings
         enabledplugin.checked = ClientWrapper.pluginModel.getPluginsEnabled()
         pluginListSettingsView.visible = enabledplugin.checked
-        if (pluginListSettingsView.visible) {
-            pluginListSettingsView.updatePluginListDisplayed()
-        }
     }
 
     function slotSetPluginEnabled(state){
@@ -114,9 +111,7 @@
                         slotSetPluginEnabled(checked)
 
                         pluginListSettingsView.visible = checked
-                        if (pluginListSettingsView.visible) {
-                            pluginListSettingsView.updatePluginListDisplayed()
-                        } else {
+                        if (!pluginListSettingsView.visible) {
                             ClientWrapper.pluginModel.toggleCallMediaHandler("", true)
                             pluginListSettingsView.hidePreferences()
                         }
@@ -144,10 +139,6 @@
                     Layout.rightMargin: 16
                     Layout.minimumHeight: 0
                     Layout.preferredHeight: childrenRect.height
-
-                    onUpdatePluginList:{
-                        pluginListSettingsView.updatePluginListDisplayed()
-                    }
                 }
             }
         }
diff --git a/src/utils.cpp b/src/utils.cpp
index f54318a..ba66fd6 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -55,7 +55,7 @@
 #include <QtConcurrent/QtConcurrent>
 
 bool
-Utils::CreateStartupLink(const std::wstring &wstrAppName)
+Utils::CreateStartupLink(const std::wstring& wstrAppName)
 {
 #ifdef Q_OS_WIN
     TCHAR szPath[MAX_PATH];
@@ -80,19 +80,19 @@
 {
 #ifdef Q_OS_WIN
     HRESULT hres;
-    IShellLink *psl;
+    IShellLink* psl;
 
     hres = CoCreateInstance(CLSID_ShellLink,
                             NULL,
                             CLSCTX_INPROC_SERVER,
                             IID_IShellLink,
-                            (LPVOID *) &psl);
+                            (LPVOID*) &psl);
     if (SUCCEEDED(hres)) {
-        IPersistFile *ppf;
+        IPersistFile* ppf;
         psl->SetPath(lpszPathObj);
         psl->SetArguments(TEXT("--minimized"));
 
-        hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *) &ppf);
+        hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*) &ppf);
         if (SUCCEEDED(hres)) {
             hres = ppf->Save(lpszPathLink, TRUE);
             ppf->Release();
@@ -108,7 +108,7 @@
 }
 
 void
-Utils::DeleteStartupLink(const std::wstring &wstrAppName)
+Utils::DeleteStartupLink(const std::wstring& wstrAppName)
 {
 #ifdef Q_OS_WIN
     TCHAR startupPath[MAX_PATH];
@@ -122,7 +122,7 @@
 }
 
 bool
-Utils::CheckStartupLink(const std::wstring &wstrAppName)
+Utils::CheckStartupLink(const std::wstring& wstrAppName)
 {
 #ifdef Q_OS_WIN
     TCHAR startupPath[MAX_PATH];
@@ -136,8 +136,8 @@
 #endif
 }
 
-const char *
-Utils::WinGetEnv(const char *name)
+const char*
+Utils::WinGetEnv(const char* name)
 {
 #ifdef Q_OS_WIN
     const DWORD buffSize = 65535;
@@ -184,8 +184,10 @@
         qDebug() << "Found startup link for Ring. Removing it and killing Ring.exe.";
         Utils::DeleteStartupLink(TEXT("Ring"));
         QProcess process;
-        process.start("taskkill", QStringList()
-                      << "/im" << "Ring.exe" << "/f");
+        process.start("taskkill",
+                      QStringList() << "/im"
+                                    << "Ring.exe"
+                                    << "/f");
         process.waitForFinished();
     }
 
@@ -213,7 +215,7 @@
 {
 #ifdef Q_OS_WIN
     GUID gidReference;
-    wchar_t *str;
+    wchar_t* str;
     HRESULT hCreateGuid = CoCreateGuid(&gidReference);
     if (hCreateGuid == S_OK) {
         StringFromCLSID(gidReference, &str);
@@ -245,7 +247,7 @@
 }
 
 void
-Utils::InvokeMailto(const QString &subject, const QString &body, const QString &attachement)
+Utils::InvokeMailto(const QString& subject, const QString& body, const QString& attachement)
 {
 #ifdef Q_OS_WIN
     HKEY hKey;
@@ -263,7 +265,7 @@
 }
 
 QString
-Utils::getContactImageString(const QString &accountId, const QString &uid)
+Utils::getContactImageString(const QString& accountId, const QString& uid)
 {
     return QString::fromLatin1(
         Utils::QImageToByteArray(
@@ -298,7 +300,7 @@
 }
 
 void
-Utils::setStackWidget(QStackedWidget *stack, QWidget *widget)
+Utils::setStackWidget(QStackedWidget* stack, QWidget* widget)
 {
     if (stack->indexOf(widget) != -1 && stack->currentWidget() != widget) {
         stack->setCurrentWidget(widget);
@@ -306,10 +308,10 @@
 }
 
 void
-Utils::showSystemNotification(QWidget *widget,
-                              const QString &message,
+Utils::showSystemNotification(QWidget* widget,
+                              const QString& message,
                               long delay,
-                              const QString &triggeredAccountId)
+                              const QString& triggeredAccountId)
 {
     if (!AppSettingsManager::getValue(Settings::Key::EnableNotifications).toBool()) {
         qWarning() << "Notifications are disabled";
@@ -321,11 +323,11 @@
 }
 
 void
-Utils::showSystemNotification(QWidget *widget,
-                              const QString &sender,
-                              const QString &message,
+Utils::showSystemNotification(QWidget* widget,
+                              const QString& sender,
+                              const QString& message,
                               long delay,
-                              const QString &triggeredAccountId)
+                              const QString& triggeredAccountId)
 {
     if (!AppSettingsManager::getValue(Settings::Key::EnableNotifications).toBool()) {
         qWarning() << "Notifications are disabled";
@@ -337,14 +339,14 @@
 }
 
 QSize
-Utils::getRealSize(QScreen *screen)
+Utils::getRealSize(QScreen* screen)
 {
 #ifdef Q_OS_WIN
     DEVMODE dmThisScreen;
     ZeroMemory(&dmThisScreen, sizeof(dmThisScreen));
-    EnumDisplaySettings((const wchar_t *) screen->name().utf16(),
+    EnumDisplaySettings((const wchar_t*) screen->name().utf16(),
                         ENUM_CURRENT_SETTINGS,
-                        (DEVMODE *) &dmThisScreen);
+                        (DEVMODE*) &dmThisScreen);
     return QSize(dmThisScreen.dmPelsWidth, dmThisScreen.dmPelsHeight);
 #else
     return {};
@@ -352,7 +354,7 @@
 }
 
 void
-Utils::forceDeleteAsync(const QString &path)
+Utils::forceDeleteAsync(const QString& path)
 {
     /*
      * Keep deleting file until the process holding it let go,
@@ -362,7 +364,7 @@
         QFile file(path);
         if (!QFile::exists(path))
             return;
-        int retries{0};
+        int retries {0};
         while (!file.remove() && retries < 5) {
             qDebug().noquote() << "\n" << file.errorString() << "\n";
             QThread::msleep(10);
@@ -371,7 +373,7 @@
     });
 }
 
-UtilsAdapter &
+UtilsAdapter&
 UtilsAdapter::instance()
 {
     static auto instance = new UtilsAdapter;
@@ -439,21 +441,21 @@
      */
     QString dir = QString(Utils::WinGetEnv("TEMP"));
     QDir log_dir(dir, {"jami*.log"});
-    for (const QString &filename : log_dir.entryList()) {
+    for (const QString& filename : log_dir.entryList()) {
         log_dir.remove(filename);
     }
     QDir msi_dir(dir, {"jami*.msi"});
-    for (const QString &filename : msi_dir.entryList()) {
+    for (const QString& filename : msi_dir.entryList()) {
         msi_dir.remove(filename);
     }
     QDir version_dir(dir, {"version"});
-    for (const QString &filename : version_dir.entryList()) {
+    for (const QString& filename : version_dir.entryList()) {
         version_dir.remove(filename);
     }
 }
 
 void
-Utils::checkForUpdates(bool withUI, QWidget *parent)
+Utils::checkForUpdates(bool withUI, QWidget* parent)
 {
     Q_UNUSED(withUI)
     Q_UNUSED(parent)
@@ -463,7 +465,7 @@
 }
 
 void
-Utils::applyUpdates(bool updateToBeta, QWidget *parent)
+Utils::applyUpdates(bool updateToBeta, QWidget* parent)
 {
     Q_UNUSED(updateToBeta)
     Q_UNUSED(parent)
@@ -473,7 +475,7 @@
 }
 
 inline QString
-removeEndlines(const QString &str)
+removeEndlines(const QString& str)
 {
     QString trimmed(str);
     trimmed.remove(QChar('\n'));
@@ -482,8 +484,8 @@
 }
 
 QString
-Utils::bestIdForConversation(const lrc::api::conversation::Info &conv,
-                             const lrc::api::ConversationModel &model)
+Utils::bestIdForConversation(const lrc::api::conversation::Info& conv,
+                             const lrc::api::ConversationModel& model)
 {
     auto contact = model.owner.contactModel->getContact(conv.participants[0]);
     if (!contact.registeredName.isEmpty()) {
@@ -493,7 +495,7 @@
 }
 
 QString
-Utils::bestIdForAccount(const lrc::api::account::Info &account)
+Utils::bestIdForAccount(const lrc::api::account::Info& account)
 {
     if (!account.registeredName.isEmpty()) {
         return removeEndlines(account.registeredName);
@@ -502,7 +504,7 @@
 }
 
 QString
-Utils::bestNameForAccount(const lrc::api::account::Info &account)
+Utils::bestNameForAccount(const lrc::api::account::Info& account)
 {
     if (account.profileInfo.alias.isEmpty()) {
         return bestIdForAccount(account);
@@ -511,7 +513,7 @@
 }
 
 QString
-Utils::bestIdForContact(const lrc::api::contact::Info &contact)
+Utils::bestIdForContact(const lrc::api::contact::Info& contact)
 {
     if (!contact.registeredName.isEmpty()) {
         return removeEndlines(contact.registeredName);
@@ -520,7 +522,7 @@
 }
 
 QString
-Utils::bestNameForContact(const lrc::api::contact::Info &contact)
+Utils::bestNameForContact(const lrc::api::contact::Info& contact)
 {
     auto alias = removeEndlines(contact.profileInfo.alias);
     if (alias.length() == 0) {
@@ -530,8 +532,8 @@
 }
 
 QString
-Utils::bestNameForConversation(const lrc::api::conversation::Info &conv,
-                               const lrc::api::ConversationModel &model)
+Utils::bestNameForConversation(const lrc::api::conversation::Info& conv,
+                               const lrc::api::ConversationModel& model)
 {
     try {
         auto contact = model.owner.contactModel->getContact(conv.participants[0]);
@@ -549,7 +551,7 @@
  * Returns empty string if only infoHash is available, second best identifier otherwise.
  */
 QString
-Utils::secondBestNameForAccount(const lrc::api::account::Info &account)
+Utils::secondBestNameForAccount(const lrc::api::account::Info& account)
 {
     auto alias = removeEndlines(account.profileInfo.alias);
     auto registeredName = removeEndlines(account.registeredName);
@@ -580,8 +582,8 @@
 }
 
 lrc::api::profile::Type
-Utils::profileType(const lrc::api::conversation::Info &conv,
-                   const lrc::api::ConversationModel &model)
+Utils::profileType(const lrc::api::conversation::Info& conv,
+                   const lrc::api::ConversationModel& model)
 {
     try {
         auto contact = model.owner.contactModel->getContact(conv.participants[0]);
@@ -592,7 +594,7 @@
 }
 
 std::string
-Utils::formatTimeString(const std::time_t &timestamp)
+Utils::formatTimeString(const std::time_t& timestamp)
 {
     std::time_t now = std::time(nullptr);
     char interactionDay[64];
@@ -609,14 +611,14 @@
 }
 
 bool
-Utils::isInteractionGenerated(const lrc::api::interaction::Type &type)
+Utils::isInteractionGenerated(const lrc::api::interaction::Type& type)
 {
     return type == lrc::api::interaction::Type::CALL
            || type == lrc::api::interaction::Type::CONTACT;
 }
 
 bool
-Utils::isContactValid(const QString &contactUid, const lrc::api::ConversationModel &model)
+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
@@ -627,7 +629,7 @@
 }
 
 bool
-Utils::getReplyMessageBox(QWidget *widget, const QString &title, const QString &text)
+Utils::getReplyMessageBox(QWidget* widget, const QString& title, const QString& text)
 {
     if (QMessageBox::question(widget, title, text, QMessageBox::Yes | QMessageBox::No)
         == QMessageBox::Yes)
@@ -636,8 +638,8 @@
 }
 
 QImage
-Utils::conversationPhoto(const QString &convUid,
-                         const lrc::api::account::Info &accountInfo,
+Utils::conversationPhoto(const QString& convUid,
+                         const lrc::api::account::Info& accountInfo,
                          bool filtered)
 {
     auto* convModel = LRCInstance::getCurrentConversationModel();
@@ -651,7 +653,7 @@
 }
 
 QColor
-Utils::getAvatarColor(const QString &canonicalUri)
+Utils::getAvatarColor(const QString& canonicalUri)
 {
     if (canonicalUri.isEmpty()) {
         return JamiAvatarTheme::defaultAvatarColor_;
@@ -667,10 +669,11 @@
 
 /* Generate a QImage representing a dummy user avatar, when user doesn't provide it.
  * Current rendering is a flat colored circle with a centered letter.
- * The color of the letter is computed from the circle color to be visible whaterver be the circle color.
+ * The color of the letter is computed from the circle color to be visible whaterver be the circle
+ * color.
  */
 QImage
-Utils::fallbackAvatar(const QSize size, const QString &canonicalUriStr, const QString &letterStr)
+Utils::fallbackAvatar(const QSize size, const QString& canonicalUriStr, const QString& letterStr)
 {
     /*
      * We start with a transparent avatar.
@@ -740,7 +743,7 @@
 }
 
 QImage
-Utils::fallbackAvatar(const QSize size, const std::string &alias, const std::string &uri)
+Utils::fallbackAvatar(const QSize size, const std::string& alias, const std::string& uri)
 {
     return fallbackAvatar(size, QString::fromStdString(uri), QString::fromStdString(alias));
 }
@@ -756,7 +759,7 @@
 }
 
 QImage
-Utils::cropImage(const QImage &img)
+Utils::cropImage(const QImage& img)
 {
     QRect rect;
     auto w = img.width();
@@ -768,7 +771,7 @@
 }
 
 QPixmap
-Utils::pixmapFromSvg(const QString &svg_resource, const QSize &size)
+Utils::pixmapFromSvg(const QString& svg_resource, const QSize& size)
 {
     QSvgRenderer svgRenderer(svg_resource);
     QPixmap pixmap(size);
@@ -799,10 +802,10 @@
     painter.setPen(QPen(Qt::black, 0.1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
     painter.setBrush(Qt::black);
     painter.fillRect(QRect(0, 0, qrwidth, qrwidth), Qt::white);
-    unsigned char *p;
+    unsigned char* p;
     p = rcode->data;
     for (int y = 0; y < rcode->width; y++) {
-        unsigned char *row = (p + (y * rcode->width));
+        unsigned char* row = (p + (y * rcode->width));
         for (int x = 0; x < rcode->width; x++) {
             if (*(row + x) & 0x1) {
                 painter.drawRect(margin + x, margin + y, 1, 1);
@@ -849,7 +852,7 @@
 }
 
 QByteArray
-Utils::QByteArrayFromFile(const QString &filename)
+Utils::QByteArrayFromFile(const QString& filename)
 {
     QFile file(filename);
     if (file.open(QIODevice::ReadOnly)) {
@@ -861,7 +864,7 @@
 }
 
 QPixmap
-Utils::generateTintedPixmap(const QString &filename, QColor color)
+Utils::generateTintedPixmap(const QString& filename, QColor color)
 {
     QPixmap px(filename);
     QImage tmpImage = px.toImage();
@@ -875,7 +878,7 @@
 }
 
 QPixmap
-Utils::generateTintedPixmap(const QPixmap &pix, QColor color)
+Utils::generateTintedPixmap(const QPixmap& pix, QColor color)
 {
     QPixmap px = pix;
     QImage tmpImage = px.toImage();
@@ -889,13 +892,13 @@
 }
 
 QImage
-Utils::scaleAndFrame(const QImage photo, const QSize &size)
+Utils::scaleAndFrame(const QImage photo, const QSize& size)
 {
     return photo.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
 }
 
 QImage
-Utils::accountPhoto(const lrc::api::account::Info &accountInfo, const QSize &size)
+Utils::accountPhoto(const lrc::api::account::Info& accountInfo, const QSize& size)
 {
     QImage photo;
     if (!accountInfo.profileInfo.avatar.isEmpty()) {
@@ -935,14 +938,14 @@
 }
 
 const QString
-UtilsAdapter::getBestName(const QString &accountId, const QString &uid)
+UtilsAdapter::getBestName(const QString& accountId, const QString& uid)
 {
     auto* convModel = LRCInstance::getAccountInfo(accountId).conversationModel.get();
     return Utils::bestNameForConversation(convModel->getConversationForUID(uid), *convModel);
 }
 
 const QString
-UtilsAdapter::getBestId(const QString &accountId, const QString &uid)
+UtilsAdapter::getBestId(const QString& accountId, const QString& uid)
 {
     auto* convModel = LRCInstance::getAccountInfo(accountId).conversationModel.get();
     return Utils::bestIdForConversation(convModel->getConversationForUID(uid), *convModel);
@@ -951,13 +954,13 @@
 int
 UtilsAdapter::getTotalUnreadMessages()
 {
-    int totalUnreadMessages{0};
+    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);
         std::for_each(ringConversations.begin(),
                       ringConversations.end(),
-                      [&totalUnreadMessages](const auto &conversation) {
+                      [&totalUnreadMessages](const auto& conversation) {
                           totalUnreadMessages += conversation.unreadMessages;
                       });
     }
@@ -967,24 +970,24 @@
 int
 UtilsAdapter::getTotalPendingRequest()
 {
-    auto &accountInfo = LRCInstance::getCurrentAccountInfo();
+    auto& accountInfo = LRCInstance::getCurrentAccountInfo();
     return accountInfo.contactModel->pendingRequestCount();
 }
 
 void
-UtilsAdapter::setConversationFilter(const QString &filter)
+UtilsAdapter::setConversationFilter(const QString& filter)
 {
     LRCInstance::getCurrentConversationModel()->setFilter(filter);
 }
 
 void
-UtilsAdapter::clearConversationHistory(const QString &accountId, const QString &uid)
+UtilsAdapter::clearConversationHistory(const QString& accountId, const QString& uid)
 {
     LRCInstance::getAccountInfo(accountId).conversationModel->clearHistory(uid);
 }
 
 void
-UtilsAdapter::removeConversation(const QString &accountId, const QString &uid, bool banContact)
+UtilsAdapter::removeConversation(const QString& accountId, const QString& uid, bool banContact)
 {
     LRCInstance::getAccountInfo(accountId).conversationModel->removeConversation(uid, banContact);
 }
@@ -1020,9 +1023,9 @@
 }
 
 void
-UtilsAdapter::setCurrentCall(const QString &accountId, const QString &convUid)
+UtilsAdapter::setCurrentCall(const QString& accountId, const QString& convUid)
 {
-    auto &accInfo = LRCInstance::getAccountInfo(accountId);
+    auto& accInfo = LRCInstance::getAccountInfo(accountId);
     const auto convInfo = accInfo.conversationModel->getConversationForUID(convUid);
     accInfo.callModel->setCurrentCall(convInfo.callId);
 }
@@ -1048,9 +1051,9 @@
 }
 
 const QString
-UtilsAdapter::getCallId(const QString &accountId, const QString &convUid)
+UtilsAdapter::getCallId(const QString& accountId, const QString& convUid)
 {
-    auto &accInfo = LRCInstance::getAccountInfo(accountId);
+    auto& accInfo = LRCInstance::getAccountInfo(accountId);
     const auto convInfo = accInfo.conversationModel->getConversationForUID(convUid);
 
     if (convInfo.uid.isEmpty()) {
@@ -1072,10 +1075,9 @@
     return lrc::api::call::to_string(status);
 }
 
-
 // returns true if name is valid registered name
 bool
-UtilsAdapter::validateRegNameForm(const QString &regName)
+UtilsAdapter::validateRegNameForm(const QString& regName)
 {
     QRegularExpression regExp(" ");
 
@@ -1111,3 +1113,11 @@
     return LRCInstance::pluginModel().getPluginsEnabled()
            && (LRCInstance::pluginModel().listLoadedPlugins().size() > 0);
 }
+
+bool
+UtilsAdapter::isImage(const QString& fileExt) const
+{
+    if (fileExt == "png" || fileExt == "jpg" || fileExt == "jpeg")
+        return true;
+    return false;
+}
diff --git a/src/utils.h b/src/utils.h
index f3d7853..4a8dfc4 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -49,7 +49,7 @@
 #include <windows.h>
 #undef ERROR
 #else
-#define LPCWSTR char *
+#define LPCWSTR char*
 #endif
 
 #include "api/account.h"
@@ -57,8 +57,8 @@
 #include "api/contactmodel.h"
 #include "api/conversationmodel.h"
 
-static const QSize IMAGE_SIZE{128, 128};
-static float CURRENT_SCALING_RATIO{1.0};
+static const QSize IMAGE_SIZE {128, 128};
+static float CURRENT_SCALING_RATIO {1.0};
 
 #ifdef BETA
 static constexpr bool isBeta = true;
@@ -71,30 +71,30 @@
 /*
  * System.
  */
-bool CreateStartupLink(const std::wstring &wstrAppName);
-void DeleteStartupLink(const std::wstring &wstrAppName);
+bool CreateStartupLink(const std::wstring& wstrAppName);
+void DeleteStartupLink(const std::wstring& wstrAppName);
 bool CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszPathLink);
-bool CheckStartupLink(const std::wstring &wstrAppName);
+bool CheckStartupLink(const std::wstring& wstrAppName);
 void removeOldVersions();
-const char *WinGetEnv(const char *name);
+const char* WinGetEnv(const char* name);
 QString GetRingtonePath();
 QString GenGUID();
 QString GetISODate();
-void InvokeMailto(const QString &subject,
-                  const QString &body,
-                  const QString &attachement = QString());
-void setStackWidget(QStackedWidget *stack, QWidget *widget);
-void showSystemNotification(QWidget *widget,
-                            const QString &message,
+void InvokeMailto(const QString& subject,
+                  const QString& body,
+                  const QString& attachement = QString());
+void setStackWidget(QStackedWidget* stack, QWidget* widget);
+void showSystemNotification(QWidget* widget,
+                            const QString& message,
                             long delay = 5000,
-                            const QString &triggeredAccountId = "");
-void showSystemNotification(QWidget *widget,
-                            const QString &sender,
-                            const QString &message,
+                            const QString& triggeredAccountId = "");
+void showSystemNotification(QWidget* widget,
+                            const QString& sender,
+                            const QString& message,
                             long delay = 5000,
-                            const QString &triggeredAccountId = "");
-QSize getRealSize(QScreen *screen);
-void forceDeleteAsync(const QString &path);
+                            const QString& triggeredAccountId = "");
+QSize getRealSize(QScreen* screen);
+void forceDeleteAsync(const QString& path);
 QString getChangeLog();
 QString getProjectCredits();
 float getCurrentScalingRatio();
@@ -104,56 +104,56 @@
  * Updates.
  */
 void cleanUpdateFiles();
-void checkForUpdates(bool withUI, QWidget *parent = nullptr);
-void applyUpdates(bool updateToBeta, QWidget *parent = nullptr);
+void checkForUpdates(bool withUI, QWidget* parent = nullptr);
+void applyUpdates(bool updateToBeta, QWidget* parent = nullptr);
 
 /*
  * Names.
  */
-QString bestIdForConversation(const lrc::api::conversation::Info &conv,
-                              const lrc::api::ConversationModel &model);
-QString bestIdForAccount(const lrc::api::account::Info &account);
-QString bestNameForAccount(const lrc::api::account::Info &account);
-QString bestIdForContact(const lrc::api::contact::Info &contact);
-QString bestNameForContact(const lrc::api::contact::Info &contact);
-QString bestNameForConversation(const lrc::api::conversation::Info &conv,
-                                const lrc::api::ConversationModel &model);
+QString bestIdForConversation(const lrc::api::conversation::Info& conv,
+                              const lrc::api::ConversationModel& model);
+QString bestIdForAccount(const lrc::api::account::Info& account);
+QString bestNameForAccount(const lrc::api::account::Info& account);
+QString bestIdForContact(const lrc::api::contact::Info& contact);
+QString bestNameForContact(const lrc::api::contact::Info& contact);
+QString bestNameForConversation(const lrc::api::conversation::Info& conv,
+                                const lrc::api::ConversationModel& model);
 /*
  * Returns empty string if only infoHash is available.
  */
-QString secondBestNameForAccount(const lrc::api::account::Info &account);
-lrc::api::profile::Type profileType(const lrc::api::conversation::Info &conv,
-                                    const lrc::api::ConversationModel &model);
+QString secondBestNameForAccount(const lrc::api::account::Info& account);
+lrc::api::profile::Type profileType(const lrc::api::conversation::Info& conv,
+                                    const lrc::api::ConversationModel& model);
 
 /*
  * Interactions.
  */
-std::string formatTimeString(const std::time_t &timestamp);
-bool isInteractionGenerated(const lrc::api::interaction::Type &interaction);
-bool isContactValid(const QString &contactUid, const lrc::api::ConversationModel &model);
-bool getReplyMessageBox(QWidget *widget, const QString &title, const QString &text);
+std::string formatTimeString(const std::time_t& timestamp);
+bool isInteractionGenerated(const lrc::api::interaction::Type& interaction);
+bool isContactValid(const QString& contactUid, const lrc::api::ConversationModel& model);
+bool getReplyMessageBox(QWidget* widget, const QString& title, const QString& text);
 
 /*
  * Image.
  */
-QString getContactImageString(const QString &accountId, const QString &uid);
+QString getContactImageString(const QString& accountId, const QString& uid);
 QImage getCirclePhoto(const QImage original, int sizePhoto);
-QImage conversationPhoto(const QString &convUid,
-                         const lrc::api::account::Info &accountInfo,
+QImage conversationPhoto(const QString& convUid,
+                         const lrc::api::account::Info& accountInfo,
                          bool filtered = false);
-QColor getAvatarColor(const QString &canonicalUri);
+QColor getAvatarColor(const QString& canonicalUri);
 QImage fallbackAvatar(const QSize size,
-                      const QString &canonicalUriStr,
-                      const QString &letterStr = QString());
-QImage fallbackAvatar(const QSize size, const std::string &alias, const std::string &uri);
+                      const QString& canonicalUriStr,
+                      const QString& letterStr = QString());
+QImage fallbackAvatar(const QSize size, const std::string& alias, const std::string& uri);
 QByteArray QImageToByteArray(QImage image);
-QByteArray QByteArrayFromFile(const QString &filename);
-QPixmap generateTintedPixmap(const QString &filename, QColor color);
-QPixmap generateTintedPixmap(const QPixmap &pix, QColor color);
-QImage scaleAndFrame(const QImage photo, const QSize &size = IMAGE_SIZE);
-QImage accountPhoto(const lrc::api::account::Info &accountInfo, const QSize &size = IMAGE_SIZE);
-QImage cropImage(const QImage &img);
-QPixmap pixmapFromSvg(const QString &svg_resource, const QSize &size);
+QByteArray QByteArrayFromFile(const QString& filename);
+QPixmap generateTintedPixmap(const QString& filename, QColor color);
+QPixmap generateTintedPixmap(const QPixmap& pix, QColor color);
+QImage scaleAndFrame(const QImage photo, const QSize& size = IMAGE_SIZE);
+QImage accountPhoto(const lrc::api::account::Info& accountInfo, const QSize& size = IMAGE_SIZE);
+QImage cropImage(const QImage& img);
+QPixmap pixmapFromSvg(const QString& svg_resource, const QSize& size);
 QImage setupQRCode(QString ringID, int margin);
 
 /*
@@ -161,9 +161,9 @@
  */
 template<typename T>
 void
-fillRoundRectPath(QPainter &painter,
-                  const T &brushType,
-                  const QRect &rectToDraw,
+fillRoundRectPath(QPainter& painter,
+                  const T& brushType,
+                  const QRect& rectToDraw,
                   qreal cornerRadius,
                   int xTransFormOffset = 0,
                   int yTransFormOffset = 0)
@@ -196,10 +196,10 @@
     Q_OBJECT
 
 public:
-    explicit OneShotDisconnectConnection(const QObject *sender,
-                                         const char *signal,
-                                         QMetaObject::Connection *connection,
-                                         QObject *parent = nullptr)
+    explicit OneShotDisconnectConnection(const QObject* sender,
+                                         const char* signal,
+                                         QMetaObject::Connection* connection,
+                                         QObject* parent = nullptr)
         : QObject(parent)
     {
         connection_ = connection;
@@ -223,8 +223,7 @@
     }
 
 public slots:
-    void
-    slotOneShotDisconnectConnection()
+    void slotOneShotDisconnectConnection()
     {
         if (connection_) {
             QObject::disconnect(*connection_);
@@ -238,19 +237,19 @@
     }
 
 private:
-    QMetaObject::Connection *connection_;
-    QMetaObject::Connection *disconnectConnection_;
+    QMetaObject::Connection* connection_;
+    QMetaObject::Connection* disconnectConnection_;
 };
 
 template<typename Func1, typename Func2>
 void
-oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,
+oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender,
                Func1 signal,
                Func2 slot)
 {
-    QMetaObject::Connection *const connection = new QMetaObject::Connection;
+    QMetaObject::Connection* const connection = new QMetaObject::Connection;
     *connection = QObject::connect(sender, signal, slot);
-    QMetaObject::Connection *const disconnectConnection = new QMetaObject::Connection;
+    QMetaObject::Connection* const disconnectConnection = new QMetaObject::Connection;
     *disconnectConnection = QObject::connect(sender, signal, [connection, disconnectConnection] {
         if (connection) {
             QObject::disconnect(*connection);
@@ -265,14 +264,14 @@
 
 template<typename Func1, typename Func2>
 void
-oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,
+oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender,
                Func1 signal,
-               const typename QtPrivate::FunctionPointer<Func2>::Object *receiver,
+               const typename QtPrivate::FunctionPointer<Func2>::Object* receiver,
                Func2 slot)
 {
-    QMetaObject::Connection *const connection = new QMetaObject::Connection;
+    QMetaObject::Connection* const connection = new QMetaObject::Connection;
     *connection = QObject::connect(sender, signal, receiver, slot);
-    QMetaObject::Connection *const disconnectConnection = new QMetaObject::Connection;
+    QMetaObject::Connection* const disconnectConnection = new QMetaObject::Connection;
     *disconnectConnection = QObject::connect(sender, signal, [connection, disconnectConnection] {
         if (connection) {
             QObject::disconnect(*connection);
@@ -286,11 +285,11 @@
 }
 
 inline void
-oneShotConnect(const QObject *sender, const char *signal, const QObject *receiver, const char *slot)
+oneShotConnect(const QObject* sender, const char* signal, const QObject* receiver, const char* slot)
 {
-    QMetaObject::Connection *const connection = new QMetaObject::Connection;
+    QMetaObject::Connection* const connection = new QMetaObject::Connection;
     *connection = QObject::connect(sender, signal, receiver, slot);
-    OneShotDisconnectConnection *disconnectConnection = new OneShotDisconnectConnection(sender,
+    OneShotDisconnectConnection* disconnectConnection = new OneShotDisconnectConnection(sender,
                                                                                         signal,
                                                                                         connection);
     Q_UNUSED(disconnectConnection)
@@ -299,33 +298,29 @@
 template<class T>
 class Blocker
 {
-    T *blocked;
+    T* blocked;
     bool previous;
 
 public:
-    Blocker(T *blocked)
+    Blocker(T* blocked)
         : blocked(blocked)
         , previous(blocked->blockSignals(true))
     {}
     ~Blocker() { blocked->blockSignals(previous); }
-    T *
-    operator->()
-    {
-        return blocked;
-    }
+    T* operator->() { return blocked; }
 };
 
 template<class T>
 inline Blocker<T>
-whileBlocking(T *blocked)
+whileBlocking(T* blocked)
 {
     return Blocker<T>(blocked);
 }
 
 template<typename T>
 void
-setElidedText(T *object,
-              const QString &text,
+setElidedText(T* object,
+              const QString& text,
               Qt::TextElideMode mode = Qt::ElideMiddle,
               int padding = 32)
 {
@@ -355,48 +350,30 @@
 {
     Q_OBJECT
 public:
-    explicit UtilsAdapter(QObject *parent = nullptr)
+    explicit UtilsAdapter(QObject* parent = nullptr)
         : QObject(parent)
     {
         clipboard_ = QApplication::clipboard();
     }
     ~UtilsAdapter() {}
 
-    ///Singleton
-    static UtilsAdapter &instance();
+    /// Singleton
+    static UtilsAdapter& instance();
 
-    Q_INVOKABLE const QString
-    getChangeLog()
-    {
-        return Utils::getChangeLog();
-    }
+    Q_INVOKABLE const QString getChangeLog() { return Utils::getChangeLog(); }
 
-    Q_INVOKABLE const QString
-    getProjectCredits()
-    {
-        return Utils::getProjectCredits();
-    }
+    Q_INVOKABLE const QString getProjectCredits() { return Utils::getProjectCredits(); }
 
-    Q_INVOKABLE const QString
-    getVersionStr()
-    {
-        return QString(VERSION_STRING);
-    }
+    Q_INVOKABLE const QString getVersionStr() { return QString(VERSION_STRING); }
 
-    Q_INVOKABLE void
-    setText(QString text)
-    {
-        clipboard_->setText(text, QClipboard::Clipboard);
-    }
+    Q_INVOKABLE void setText(QString text) { clipboard_->setText(text, QClipboard::Clipboard); }
 
-    Q_INVOKABLE const QString
-    qStringFromFile(const QString &filename)
+    Q_INVOKABLE const QString qStringFromFile(const QString& filename)
     {
         return Utils::QByteArrayFromFile(filename);
     }
 
-    Q_INVOKABLE const QString
-    getStyleSheet(const QString &name, const QString &source)
+    Q_INVOKABLE const QString getStyleSheet(const QString& name, const QString& source)
     {
         auto simplifiedCSS = source.simplified().replace("'", "\"");
         QString s = QString::fromLatin1("(function() {"
@@ -410,88 +387,66 @@
         return s;
     }
 
-    Q_INVOKABLE const QString
-    getCachePath()
+    Q_INVOKABLE const QString getCachePath()
     {
         QDir dataDir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
         dataDir.cdUp();
         return dataDir.absolutePath() + "/jami";
     }
-    Q_INVOKABLE bool
-    createStartupLink()
-    {
-        return Utils::CreateStartupLink(L"Jami");
-    }
-    Q_INVOKABLE QString
-    GetRingtonePath()
-    {
-        return Utils::GetRingtonePath();
-    }
-    Q_INVOKABLE bool
-    checkStartupLink()
-    {
-        return Utils::CheckStartupLink(L"Jami");
-    }
+    Q_INVOKABLE bool createStartupLink() { return Utils::CreateStartupLink(L"Jami"); }
+    Q_INVOKABLE QString GetRingtonePath() { return Utils::GetRingtonePath(); }
+    Q_INVOKABLE bool checkStartupLink() { return Utils::CheckStartupLink(L"Jami"); }
 
-    Q_INVOKABLE const QString
-    getContactImageString(const QString &accountId, const QString &uid)
+    Q_INVOKABLE const QString getContactImageString(const QString& accountId, const QString& uid)
     {
         return Utils::getContactImageString(accountId, uid);
     }
 
-    Q_INVOKABLE void removeConversation(const QString &accountId,
-                                        const QString &uid,
+    Q_INVOKABLE void removeConversation(const QString& accountId,
+                                        const QString& uid,
                                         bool banContact = false);
-    Q_INVOKABLE void clearConversationHistory(const QString &accountId, const QString &uid);
-    Q_INVOKABLE void setConversationFilter(const QString &filter);
+    Q_INVOKABLE void clearConversationHistory(const QString& accountId, const QString& uid);
+    Q_INVOKABLE void setConversationFilter(const QString& filter);
     Q_INVOKABLE int getTotalUnreadMessages();
     Q_INVOKABLE int getTotalPendingRequest();
-    Q_INVOKABLE const QString getBestName(const QString &accountId, const QString &uid);
-    Q_INVOKABLE const QString getBestId(const QString &accountId, const QString &uid);
+    Q_INVOKABLE const QString getBestName(const QString& accountId, const QString& uid);
+    Q_INVOKABLE const QString getBestId(const QString& accountId, const QString& uid);
 
     Q_INVOKABLE const QString getCurrAccId();
     Q_INVOKABLE const QString getCurrConvId();
     Q_INVOKABLE void makePermanentCurrentConv();
     Q_INVOKABLE const QStringList getCurrAccList();
     Q_INVOKABLE int getAccountListSize();
-    Q_INVOKABLE void setCurrentCall(const QString &accountId, const QString &convUid);
+    Q_INVOKABLE void setCurrentCall(const QString& accountId, const QString& convUid);
     Q_INVOKABLE void startPreviewing(bool force);
     Q_INVOKABLE void stopPreviewing();
     Q_INVOKABLE bool hasVideoCall();
-    Q_INVOKABLE const QString getCallId(const QString &accountId, const QString &convUid);
+    Q_INVOKABLE const QString getCallId(const QString& accountId, const QString& convUid);
     Q_INVOKABLE const QString getCallStatusStr(int statusInt);
     Q_INVOKABLE QString getStringUTF8(QString string);
-    Q_INVOKABLE bool validateRegNameForm(const QString &regName);
+    Q_INVOKABLE bool validateRegNameForm(const QString& regName);
     Q_INVOKABLE QString getRecordQualityString(int value);
     Q_INVOKABLE QString getCurrentPath();
-    Q_INVOKABLE QString
-    stringSimplifier(QString input)
-    {
-        return input.simplified();
-    }
+    Q_INVOKABLE QString stringSimplifier(QString input) { return input.simplified(); }
 
-    Q_INVOKABLE QString
-    toNativeSeparators(QString inputDir)
+    Q_INVOKABLE QString toNativeSeparators(QString inputDir)
     {
         return QDir::toNativeSeparators(inputDir);
     }
 
-    Q_INVOKABLE QString
-    toFileInfoName(QString inputFileName)
+    Q_INVOKABLE QString toFileInfoName(QString inputFileName)
     {
         QFileInfo fi(inputFileName);
         return fi.fileName();
     }
 
-    Q_INVOKABLE QString
-    toFileAbsolutepath(QString inputFileName)
+    Q_INVOKABLE QString toFileAbsolutepath(QString inputFileName)
     {
         QFileInfo fi(inputFileName);
         return fi.absolutePath();
     }
 
-    Q_INVOKABLE QString
-    getAbsPath(QString path)
+    Q_INVOKABLE QString getAbsPath(QString path)
     {
 #ifdef Q_OS_WIN
         return path.replace("file:///", "").replace("\n", "").replace("\r", "");
@@ -500,8 +455,7 @@
 #endif
     }
 
-    Q_INVOKABLE QString
-    getCroppedImageBase64FromFile(QString fileName, int size)
+    Q_INVOKABLE QString getCroppedImageBase64FromFile(QString fileName, int size)
     {
         auto image = Utils::cropImage(QImage(fileName));
         auto croppedImage = image.scaled(size,
@@ -513,7 +467,21 @@
 
     Q_INVOKABLE bool checkShowPluginsButton();
 
+    Q_INVOKABLE QString fileName(const QString& path)
+    {
+        QFileInfo fi(path);
+        return fi.fileName();
+    }
+
+    Q_INVOKABLE QString getExt(const QString& path)
+    {
+        QFileInfo fi(path);
+        return fi.completeSuffix();
+    }
+
+    Q_INVOKABLE bool isImage(const QString& fileExt) const;
+
 private:
-    QClipboard *clipboard_;
+    QClipboard* clipboard_;
 };
-Q_DECLARE_METATYPE(UtilsAdapter *)
+Q_DECLARE_METATYPE(UtilsAdapter*)