1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-09-10 12:03:18 +02:00

qml interop: start replacing QMetaObject::invokeMethod with signals

It seems concurrent calls to invokeMethod using qml component
object pointers can lead to access violations. These method
invocations can be replaced with a signal/slot mechanism.

This patch replaces only the invocations in conversationsadapter
and accountsadapter that are known to be problematic for now.

Some code cleanup is done for QmlAdapterBase derived classes.

Gitlab: #61
Change-Id: I72f47c9229a9bf42299ae52822c3a1a8c04eb423
This commit is contained in:
Andreas Traczyk 2020-09-03 09:24:49 -04:00
parent 346b255c77
commit eb53a622b7
22 changed files with 147 additions and 191 deletions

View file

@ -174,7 +174,6 @@ SOURCES += ./src/bannedlistmodel.cpp \
./src/conversationsadapter.cpp \
./src/distantrenderer.cpp \
./src/previewrenderer.cpp \
./src/qmladapterbase.cpp \
./src/avadapter.cpp \
./src/contactadapter.cpp \
./src/mediahandleradapter.cpp \

View file

@ -30,8 +30,6 @@ AccountAdapter::AccountAdapter(QObject *parent)
: QmlAdapterBase(parent)
{}
AccountAdapter::~AccountAdapter() {}
AccountAdapter &
AccountAdapter::instance()
{
@ -40,7 +38,7 @@ AccountAdapter::instance()
}
void
AccountAdapter::initQmlObject()
AccountAdapter::safeInit()
{
setSelectedAccount(LRCInstance::getCurrAccId());
}
@ -334,7 +332,7 @@ void
AccountAdapter::backToWelcomePage()
{
deselectConversation();
QMetaObject::invokeMethod(qmlObj_, "backToWelcomePage");
emit navigateToWelcomePageRequested();
}
void

View file

@ -27,13 +27,18 @@
#include "lrcinstance.h"
#include "utils.h"
class AccountAdapter : public QmlAdapterBase
class AccountAdapter final : public QmlAdapterBase
{
Q_OBJECT
public:
explicit AccountAdapter(QObject *parent = 0);
~AccountAdapter();
~AccountAdapter() = default;
protected:
void safeInit() override;
public:
//Singleton
static AccountAdapter &instance();
@ -94,9 +99,9 @@ signals:
*/
void reportFailure();
void accountAdded(bool showBackUp, int index);
void navigateToWelcomePageRequested();
private:
void initQmlObject() override final;
void setSelectedAccount(const QString &accountId);
void backToWelcomePage();
void deselectConversation();

View file

@ -28,12 +28,6 @@ AvAdapter::AvAdapter(QObject *parent)
: QmlAdapterBase(parent)
{}
AvAdapter::~AvAdapter() {}
void
AvAdapter::initQmlObject()
{}
QVariantMap
AvAdapter::populateVideoDeviceContextMenuItem()
{

View file

@ -24,13 +24,16 @@
#include <QVariant>
#include <QString>
class AvAdapter : public QmlAdapterBase
class AvAdapter final : public QmlAdapterBase
{
Q_OBJECT
public:
explicit AvAdapter(QObject *parent = nullptr);
~AvAdapter();
~AvAdapter() = default;
protected:
void safeInit() override {};
/*
* Return needed info for populating video device context menu item.
@ -62,6 +65,4 @@ public:
*/
Q_INVOKABLE void shareScreenArea(int screenNumber, int x, int y, int width, int height);
private:
void initQmlObject() override;
};

View file

@ -30,12 +30,6 @@
CallAdapter::CallAdapter(QObject* parent)
: QmlAdapterBase(parent)
, oneSecondTimer_(new QTimer(this))
{}
CallAdapter::~CallAdapter() {}
void
CallAdapter::initQmlObject()
{
connectCallModel(LRCInstance::getCurrAccId());
@ -676,4 +670,4 @@ CallAdapter::setTime(const QString& accountId, const QString& convUid)
auto timeString = LRCInstance::getCurrentCallModel()->getFormattedCallDuration(callId);
emit updateTimeText(timeString);
}
}
}

View file

@ -26,19 +26,18 @@
#include <QString>
#include <QVariant>
class CallAdapter : public QmlAdapterBase
class CallAdapter final : public QmlAdapterBase
{
Q_OBJECT
public:
explicit CallAdapter(QObject* parent = nullptr);
~CallAdapter();
~CallAdapter() = default;
/*
* This is needed to be public since it has to be recognized by qml.
*/
Q_INVOKABLE void initQmlObject() override;
protected:
void safeInit() override {};
public:
Q_INVOKABLE void placeAudioOnlyCall();
Q_INVOKABLE void placeCall();
Q_INVOKABLE void hangUpACall(const QString& accountId, const QString& convUid);

View file

@ -1,4 +1,4 @@
/*
/*!
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
@ -28,8 +28,6 @@ ContactAdapter::ContactAdapter(QObject *parent)
selectableProxyModel_.reset(new SelectableProxyModel(smartListModel_.get()));
}
ContactAdapter::~ContactAdapter() {}
QVariant
ContactAdapter::getContactSelectableModel(int type)
{
@ -175,7 +173,3 @@ ContactAdapter::setCalleeDisplayName(const QString &name)
{
calleeDisplayName_ = name;
}
void
ContactAdapter::initQmlObject()
{}

View file

@ -1,4 +1,4 @@
/*
/*!
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
*
@ -34,7 +34,7 @@
*
* Additionally, user need to setFilterRegExp to be able to get input QRegExp from FilterPredicate.
*/
class SelectableProxyModel : public QSortFilterProxyModel
class SelectableProxyModel final : public QSortFilterProxyModel
{
public:
using FilterPredicate = std::function<bool(const QModelIndex &, const QRegExp &)>;
@ -68,13 +68,16 @@ private:
std::function<bool(const QModelIndex &, const QRegExp &)> filterPredicate_;
};
class ContactAdapter : public QmlAdapterBase
class ContactAdapter final : public QmlAdapterBase
{
Q_OBJECT
public:
explicit ContactAdapter(QObject *parent = nullptr);
~ContactAdapter();
~ContactAdapter() = default;
protected:
void safeInit() override {};
Q_INVOKABLE QVariant getContactSelectableModel(int type);
Q_INVOKABLE void setSearchFilter(const QString &filter);
@ -82,8 +85,6 @@ public:
Q_INVOKABLE void setCalleeDisplayName(const QString &name);
private:
void initQmlObject() override;
SmartListModel::Type listModeltype_;
/*

View file

@ -1,4 +1,4 @@
/*
/*!
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>
* Author: Anthony Lonard <anthony.leonard@savoirfairelinux.com>
@ -29,15 +29,12 @@ ConversationsAdapter::ConversationsAdapter(QObject *parent)
: QmlAdapterBase(parent)
{}
ConversationsAdapter::~ConversationsAdapter() {}
void
ConversationsAdapter::initQmlObject()
ConversationsAdapter::safeInit()
{
conversationSmartListModel_ = new SmartListModel(LRCInstance::getCurrAccId(), this);
QMetaObject::invokeMethod(qmlObj_, "setModel",
Q_ARG(QVariant, QVariant::fromValue(conversationSmartListModel_)));
emit modelChanged(QVariant::fromValue(conversationSmartListModel_));
connect(&LRCInstance::behaviorController(),
&BehaviorController::showChatView,
@ -57,7 +54,7 @@ void
ConversationsAdapter::backToWelcomePage()
{
deselectConversation();
QMetaObject::invokeMethod(qmlObj_, "backToWelcomePage");
emit navigateToWelcomePageRequested();
}
void
@ -198,7 +195,7 @@ ConversationsAdapter::connectConversationModel(bool updateFilter)
[this]() {
conversationSmartListModel_->fillConversationsList();
updateConversationsFilterWidget();
QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
emit updateListViewRequested();
auto* convModel = LRCInstance::getCurrentConversationModel();
const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid());
@ -211,7 +208,7 @@ ConversationsAdapter::connectConversationModel(bool updateFilter)
== lrc::api::profile::Type::TEMPORARY) {
return;
}
QMetaObject::invokeMethod(qmlObj_, "modelSorted", Q_ARG(QVariant, contactURI));
emit modelSorted(QVariant::fromValue(contactURI));
});
modelUpdatedConnection_ = QObject::connect(currentConversationModel,
@ -219,7 +216,7 @@ ConversationsAdapter::connectConversationModel(bool updateFilter)
[this](const QString &convUid) {
conversationSmartListModel_->updateConversation(convUid);
updateConversationsFilterWidget();
QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
emit updateListViewRequested();
});
filterChangedConnection_ = QObject::connect(currentConversationModel,
@ -228,7 +225,7 @@ ConversationsAdapter::connectConversationModel(bool updateFilter)
conversationSmartListModel_->fillConversationsList();
conversationSmartListModel_->setAccount(LRCInstance::getCurrAccId());
updateConversationsFilterWidget();
QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
emit updateListViewRequested();
});
newConversationConnection_ = QObject::connect(currentConversationModel,
@ -265,9 +262,10 @@ ConversationsAdapter::connectConversationModel(bool updateFilter)
searchResultUpdatedConnection_ = QObject::connect(currentConversationModel,
&lrc::api::ConversationModel::searchResultUpdated,
[this]() {
conversationSmartListModel_->fillConversationsList();
conversationSmartListModel_->setAccount(LRCInstance::getCurrAccId());
QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView");
emit updateListViewRequested();
});
if (updateFilter) currentConversationModel->setFilter("");

View file

@ -1,4 +1,4 @@
/*
/*!
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
*
@ -25,14 +25,17 @@
#include <QObject>
#include <QString>
class ConversationsAdapter : public QmlAdapterBase
class ConversationsAdapter final : public QmlAdapterBase
{
Q_OBJECT
public:
explicit ConversationsAdapter(QObject *parent = nullptr);
~ConversationsAdapter();
~ConversationsAdapter() = default;
protected:
void safeInit() override;
public:
Q_INVOKABLE bool connectConversationModel(bool updateFilter = true);
Q_INVOKABLE void disconnectConversationModel();
Q_INVOKABLE void selectConversation(const QString &accountId,
@ -50,8 +53,12 @@ signals:
void showConversationTabs(bool visible);
void showSearchStatus(const QString &status);
void modelChanged(const QVariant& model);
void modelSorted(const QVariant& uri);
void updateListViewRequested();
void navigateToWelcomePageRequested();
private:
void initQmlObject() override;
void setConversationFilter(lrc::api::profile::Type filter);
void backToWelcomePage();
bool selectConversation(const lrc::api::conversation::Info &item,

View file

@ -704,10 +704,6 @@ Window {
height: userProfile.contentHeight
}
Component.onCompleted: {
CallAdapter.initQmlObject()
}
onClosing: {
close.accepted = false
mainViewWindow.hide()

View file

@ -27,14 +27,10 @@ ComboBox {
id: accountComboBox
signal accountChanged(int index)
signal needToBackToWelcomePage()
signal needToBackToWelcomePage
signal newAccountButtonClicked
signal settingBtnClicked
function backToWelcomePage() {
needToBackToWelcomePage()
}
// Reset accountListModel.
function resetAccountListModel() {
accountListModel.reset()
@ -53,6 +49,14 @@ ComboBox {
}
}
Connections {
target: ClientWrapper.accountAdaptor
function onNavigateToWelcomePageRequested() {
needToBackToWelcomePage()
}
}
Image {
id: userImageRoot

View file

@ -1,7 +1,7 @@
/*
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
* Author: Andreas Traczyk <andreas.traczyk@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
@ -16,13 +16,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import net.jami.Models 1.0
ListView {
id: conversationSmartListView
id: root
signal needToAccessMessageWebView(string currentUserDisplayName, string currentUserAlias, string currentUID, bool callStackViewShouldShow, bool isAudioOnly, int callState)
signal needToSelectItems(string conversationUid)
@ -34,60 +35,59 @@ ListView {
signal currentIndexIsChanged
signal forceUpdatePotentialInvalidItem
/*
* When model is sorted, we need to reset to focus (currentIndex)
* to the real conversation that we focused.
*/
function modelSorted(contactURIToCompare) {
var conversationSmartListViewModel = conversationSmartListView.model
conversationSmartListView.currentIndex = -1
updateConversationSmartListView()
for (var i = 0; i < count; i++) {
if (conversationSmartListViewModel.data(
conversationSmartListViewModel.index(i, 0),
261) === contactURIToCompare) {
conversationSmartListView.currentIndex = i
break
}
}
}
/*
* Refresh all item within model.
*/
function updateConversationSmartListView() {
var conversationSmartListViewModel = conversationSmartListView.model
conversationSmartListViewModel.dataChanged(
conversationSmartListViewModel.index(0, 0),
conversationSmartListViewModel.index(
conversationSmartListViewModel.rowCount() - 1, 0))
conversationSmartListView.forceUpdatePotentialInvalidItem()
}
function setModel(model) {
conversationSmartListView.model = model
}
function backToWelcomePage() {
conversationSmartListView.needToBackToWelcomePage()
// Refresh all items within the model.
function updateListView() {
root.model.dataChanged(
root.model.index(0, 0),
root.model.index(
root.model.rowCount() - 1, 0))
root.forceUpdatePotentialInvalidItem()
}
ConversationSmartListContextMenu {
id: smartListContextMenu
}
Connections {
target: ConversationsAdapter
function onModelChanged(model) {
root.model = model
}
// When the model has been sorted, we need to adjust the focus (currentIndex)
// to the previously focused conversation item.
function onModelSorted(uri) {
root.currentIndex = -1
updateListView()
for (var i = 0; i < count; i++) {
if (root.model.data(
root.model.index(i, 0), 261) === uri) {
root.currentIndex = i
break
}
}
}
function onUpdateListViewRequested() {
updateListView()
}
function onNavigateToWelcomePageRequested() {
root.needToBackToWelcomePage()
}
}
Connections {
target: CallAdapter
function onUpdateConversationSmartList() {
updateConversationSmartListView()
updateListView()
}
}
onCurrentIndexChanged: {
conversationSmartListView.currentIndexIsChanged()
root.currentIndexIsChanged()
}
clip: true
@ -101,7 +101,7 @@ ListView {
Shortcut {
sequence: "Ctrl+Shift+X"
context: Qt.ApplicationShortcut
enabled: conversationSmartListView.visible
enabled: root.visible
onActivated: {
CallAdapter.placeCall()
}
@ -110,7 +110,7 @@ ListView {
Shortcut {
sequence: "Ctrl+Shift+C"
context: Qt.ApplicationShortcut
enabled: conversationSmartListView.visible
enabled: root.visible
onActivated: {
CallAdapter.placeAudioOnlyCall()
}
@ -119,7 +119,7 @@ ListView {
Shortcut {
sequence: "Ctrl+Shift+L"
context: Qt.ApplicationShortcut
enabled: conversationSmartListView.visible
enabled: root.visible
onActivated: {
ClientWrapper.utilsAdaptor.clearConversationHistory(ClientWrapper.utilsAdaptor.getCurrAccId(),
ClientWrapper.utilsAdaptor.getCurrConvId())
@ -129,18 +129,18 @@ ListView {
Shortcut {
sequence: "Ctrl+Shift+B"
context: Qt.ApplicationShortcut
enabled: conversationSmartListView.visible
enabled: root.visible
onActivated: {
ClientWrapper.utilsAdaptor.removeConversation(ClientWrapper.utilsAdaptor.getCurrAccId(),
ClientWrapper.utilsAdaptor.getCurrConvId(), true)
conversationSmartListView.needToBackToWelcomePage()
root.needToBackToWelcomePage()
}
}
Shortcut {
sequence: "Ctrl+Shift+Delete"
context: Qt.ApplicationShortcut
enabled: conversationSmartListView.visible
enabled: root.visible
onActivated: {
ClientWrapper.utilsAdaptor.removeConversation(ClientWrapper.utilsAdaptor.getCurrAccId(),
ClientWrapper.utilsAdaptor.getCurrConvId(), false)
@ -150,21 +150,22 @@ ListView {
Shortcut {
sequence: "Ctrl+Down"
context: Qt.ApplicationShortcut
enabled: conversationSmartListView.visible
enabled: root.visible
onActivated: {
if (currentIndex + 1 >= count) return
conversationSmartListView.currentIndex += 1
if (currentIndex + 1 >= count)
return
root.currentIndex += 1
}
}
Shortcut {
sequence: "Ctrl+Up"
context: Qt.ApplicationShortcut
enabled: conversationSmartListView.visible
enabled: root.visible
onActivated: {
if (currentIndex <= 0) return
conversationSmartListView.currentIndex -= 1
if (currentIndex <= 0)
return
root.currentIndex -= 1
}
}
}

View file

@ -91,7 +91,7 @@ Rectangle {
}
function forceUpdateConversationSmartListView() {
conversationSmartListView.updateConversationSmartListView()
conversationSmartListView.updateListView()
}
/*

View file

@ -24,8 +24,6 @@ MediaHandlerAdapter::MediaHandlerAdapter(QObject* parent)
: QmlAdapterBase(parent)
{}
MediaHandlerAdapter::~MediaHandlerAdapter() {}
QVariant
MediaHandlerAdapter::getMediaHandlerSelectableModel()
{
@ -61,7 +59,3 @@ MediaHandlerAdapter::getMediaHandlerPreferencesSelectableModel(QString pluginId)
return QVariant::fromValue(mediaHandlerListPreferenceModel_.get());
}
void
MediaHandlerAdapter::initQmlObject()
{}

View file

@ -1,4 +1,4 @@
/**
/*!
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
*
@ -19,7 +19,6 @@
#pragma once
#include "qmladapterbase.h"
//#include "smartlistmodel.h"
#include "mediahandleritemlistmodel.h"
#include "mediahandlerlistpreferencemodel.h"
#include "preferenceitemlistmodel.h"
@ -28,22 +27,23 @@
#include <QSortFilterProxyModel>
#include <QString>
class MediaHandlerAdapter : public QmlAdapterBase
class MediaHandlerAdapter final : public QmlAdapterBase
{
Q_OBJECT
public:
explicit MediaHandlerAdapter(QObject* parent = nullptr);
~MediaHandlerAdapter();
~MediaHandlerAdapter() = default;
protected:
void safeInit() override {};
Q_INVOKABLE QVariant getMediaHandlerSelectableModel();
Q_INVOKABLE QVariant getMediaHandlerPreferencesModel(QString pluginId, QString mediaHandlerName);
Q_INVOKABLE QVariant getMediaHandlerPreferencesSelectableModel(QString pluginId);
private:
void initQmlObject();
std::unique_ptr<MediaHandlerItemListModel> mediaHandlerListModel_;
std::unique_ptr<PreferenceItemListModel> mediaHandlerPreferenceItemListModel_;
std::unique_ptr<MediaHandlerListPreferenceModel> mediaHandlerListPreferenceModel_;
};

View file

@ -1,7 +1,7 @@
/*
/*!
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>
* Author: Anthony Lonard <anthony.leonard@savoirfairelinux.com>
* Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com>
* Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com>
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
* Author: Isa Nanic <isa.nanic@savoirfairelinux.com>
@ -22,9 +22,9 @@
*/
#include "messagesadapter.h"
#include "webchathelpers.h"
#include "utils.h"
#include "webchathelpers.h"
#include <QDesktopServices>
#include <QFileInfo>
@ -36,10 +36,8 @@ MessagesAdapter::MessagesAdapter(QObject *parent)
: QmlAdapterBase(parent)
{}
MessagesAdapter::~MessagesAdapter() {}
void
MessagesAdapter::initQmlObject() {
MessagesAdapter::safeInit() {
connect(&LRCInstance::instance(),
&LRCInstance::currentAccountChanged,
[this](){

View file

@ -1,4 +1,4 @@
/*
/*!
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
*
@ -24,13 +24,15 @@
#include <QObject>
#include <QString>
class MessagesAdapter : public QmlAdapterBase
class MessagesAdapter final : public QmlAdapterBase
{
Q_OBJECT
public:
explicit MessagesAdapter(QObject *parent = 0);
~MessagesAdapter();
~MessagesAdapter() = default;
protected:
void safeInit() override;
Q_INVOKABLE void setupChatView(const QString &uid);
Q_INVOKABLE void connectConversationModel();
@ -93,7 +95,6 @@ public slots:
void slotMessagesLoaded();
private:
void initQmlObject() override final;
void setConversationProfileData(const lrc::api::conversation::Info &convInfo);
void newInteraction(const QString &accountId,
const QString &convUid,

View file

@ -1,35 +0,0 @@
/*
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Mingrui Zhang <mingrui.zhang@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 "qmladapterbase.h"
QmlAdapterBase::QmlAdapterBase(QObject *parent)
: QObject(parent)
{
qmlObj_ = nullptr;
}
QmlAdapterBase::~QmlAdapterBase() {}
void
QmlAdapterBase::setQmlObject(QObject *obj)
{
qmlObj_ = obj;
initQmlObject();
}

View file

@ -28,20 +28,27 @@ class QmlAdapterBase : public QObject
{
Q_OBJECT
public:
explicit QmlAdapterBase(QObject *parent = nullptr);
~QmlAdapterBase();
explicit QmlAdapterBase(QObject *parent = nullptr)
: QObject(parent)
, qmlObj_(nullptr) {};
virtual ~QmlAdapterBase() = default;
/*
* This function should be called in the Component.onCompleted slot
* in the qml component that this adapter should attach to.
*/
Q_INVOKABLE void setQmlObject(QObject *obj);
Q_INVOKABLE void setQmlObject(QObject *obj)
{
qmlObj_ = obj;
safeInit();
};
protected:
/*
*Once the qml object is set, custom actions can be done in this function.
* Once the qml object is set, Qml method invokation can be done
*/
virtual void initQmlObject() = 0;
virtual void safeInit() = 0;
/*
* Object pointer.

View file

@ -135,6 +135,7 @@ void registerTypes()
QML_REGISTERSINGLETONTYPE_URL(QStringLiteral("qrc:/src/constant/JamiQmlUtils.qml"),
JamiQmlUtils, 1, 0);
QML_REGISTERSINGLETONTYPE("net.jami.Models", AccountAdapter, 1, 0);
QML_REGISTERSINGLETONTYPE("net.jami.Models", CallAdapter, 1, 0);
QML_REGISTERSINGLETONTYPE("net.jami.Models", MessagesAdapter, 1, 0);
QML_REGISTERSINGLETONTYPE("net.jami.Models", ConversationsAdapter, 1, 0);
@ -167,7 +168,6 @@ void registerTypes()
* qmlRegisterUncreatableType & Q_DECLARE_METATYPE to expose models in qml.
*/
QML_REGISTERUNCREATABLE("net.jami.Models", RenderManager, 1, 0);
QML_REGISTERUNCREATABLE("net.jami.Models", AccountAdapter, 1, 0);
QML_REGISTERUNCREATABLE("net.jami.Models", UtilsAdapter, 1, 0);
QML_REGISTERUNCREATABLE("net.jami.Models", NameDirectory, 1, 0);
QML_REGISTERUNCREATABLE("net.jami.Models", LRCInstance, 1, 0);