mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2024-10-28 00:39:36 +01:00
qmlregister: improve singleton registration
- better manage QML interop object lifetimes - allow intellisense to pick up QML registered symbols - fix for PreviewEngine threading Change-Id: I416cdede70b155dc34fc3ee94f428ae2128c8950
This commit is contained in:
parent
c8b52262bc
commit
35f850289f
58 changed files with 658 additions and 491 deletions
1
.clang-tidy
Normal file
1
.clang-tidy
Normal file
|
@ -0,0 +1 @@
|
|||
Checks: '-*,analyzer-cplusplus.NewDeleteLeaks'
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "appsettingsmanager.h"
|
||||
#include "qtutils.h"
|
||||
#include "qmlregister.h"
|
||||
#include "accountlistmodel.h"
|
||||
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
|
@ -33,14 +33,7 @@ AccountAdapter::AccountAdapter(AppSettingsManager* settingsManager,
|
|||
: QmlAdapterBase(instance, parent)
|
||||
, settingsManager_(settingsManager)
|
||||
, systemTray_(systemTray)
|
||||
, accountListModel_(new AccountListModel(instance))
|
||||
, deviceItemListModel_(new DeviceItemListModel(instance, parent))
|
||||
, moderatorListModel_(new ModeratorListModel(instance, parent))
|
||||
{
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, accountListModel_.get(), "AccountListModel");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, deviceItemListModel_.get(), "DeviceItemListModel");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, moderatorListModel_.get(), "ModeratorListModel");
|
||||
|
||||
connect(&lrcInstance_->accountModel(),
|
||||
&AccountModel::accountStatusChanged,
|
||||
this,
|
||||
|
@ -53,8 +46,13 @@ AccountAdapter::AccountAdapter(AppSettingsManager* settingsManager,
|
|||
|
||||
connect(systemTray_,
|
||||
&SystemTray::countChanged,
|
||||
accountListModel_.get(),
|
||||
qApp->property("AccountListModel").value<AccountListModel*>(),
|
||||
&AccountListModel::updateNotifications);
|
||||
|
||||
// Switch account to the specified index when an account is added.
|
||||
connect(this, &AccountAdapter::accountAdded, this, [this](const QString&, int index) {
|
||||
changeAccount(index);
|
||||
});
|
||||
}
|
||||
|
||||
AccountModel*
|
||||
|
|
|
@ -20,21 +20,20 @@
|
|||
|
||||
#include "qmladapterbase.h"
|
||||
|
||||
#include "accountlistmodel.h"
|
||||
#include "deviceitemlistmodel.h"
|
||||
#include "moderatorlistmodel.h"
|
||||
#include "systemtray.h"
|
||||
#include "lrcinstance.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QString>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class AppSettingsManager;
|
||||
|
||||
class AccountAdapter final : public QmlAdapterBase
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
Q_PROPERTY(lrc::api::AccountModel* model READ getModel NOTIFY modelChanged)
|
||||
|
||||
|
@ -45,6 +44,13 @@ Q_SIGNALS:
|
|||
void modelChanged();
|
||||
|
||||
public:
|
||||
static AccountAdapter* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new AccountAdapter(qApp->property("AppSettingsManager").value<AppSettingsManager*>(),
|
||||
qApp->property("SystemTray").value<SystemTray*>(),
|
||||
qApp->property("LRCInstance").value<LRCInstance*>());
|
||||
}
|
||||
|
||||
explicit AccountAdapter(AppSettingsManager* settingsManager,
|
||||
SystemTray* systemTray,
|
||||
LRCInstance* instance,
|
||||
|
@ -100,9 +106,5 @@ private:
|
|||
|
||||
AppSettingsManager* settingsManager_;
|
||||
SystemTray* systemTray_;
|
||||
|
||||
QScopedPointer<AccountListModel> accountListModel_;
|
||||
QScopedPointer<DeviceItemListModel> deviceItemListModel_;
|
||||
QScopedPointer<ModeratorListModel> moderatorListModel_;
|
||||
};
|
||||
Q_DECLARE_METATYPE(AccountAdapter*)
|
||||
|
|
|
@ -20,11 +20,8 @@
|
|||
#include "accountlistmodel.h"
|
||||
|
||||
#include "lrcinstance.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "api/account.h"
|
||||
#include "api/contact.h"
|
||||
#include "api/conversation.h"
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
|
|
|
@ -51,11 +51,9 @@ public:
|
|||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
// reset the model when there's new account added
|
||||
Q_INVOKABLE void reset();
|
||||
|
||||
void updateNotifications();
|
||||
|
||||
protected:
|
||||
private:
|
||||
using Role = AccountList::Role;
|
||||
};
|
||||
|
|
|
@ -20,23 +20,31 @@
|
|||
|
||||
#include "qmladapterbase.h"
|
||||
#include "lrcinstance.h"
|
||||
#include "qtutils.h"
|
||||
#include "rendererinformationlistmodel.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <qtutils.h>
|
||||
|
||||
#include "rendererinformationlistmodel.h"
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class AvAdapter final : public QmlAdapterBase
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
QML_PROPERTY(bool, muteCamera)
|
||||
QML_RO_PROPERTY(QStringList, windowsNames)
|
||||
QML_RO_PROPERTY(QList<QVariant>, windowsIds)
|
||||
QML_RO_PROPERTY(QVariant, renderersInfoList)
|
||||
|
||||
public:
|
||||
static AvAdapter* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new AvAdapter(qApp->property("LRCInstance").value<LRCInstance*>());
|
||||
}
|
||||
|
||||
explicit AvAdapter(LRCInstance* instance, QObject* parent = nullptr);
|
||||
~AvAdapter() = default;
|
||||
|
||||
|
|
|
@ -20,13 +20,22 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class LRCInstance;
|
||||
|
||||
class AvatarRegistry : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
public:
|
||||
static AvatarRegistry* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new AvatarRegistry(qApp->property("LRCInstance").value<LRCInstance*>());
|
||||
}
|
||||
|
||||
explicit AvatarRegistry(LRCInstance* instance, QObject* parent = nullptr);
|
||||
~AvatarRegistry() = default;
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
#include "calladapter.h"
|
||||
|
||||
#include "systemtray.h"
|
||||
#include "qmlregister.h"
|
||||
#include "appsettingsmanager.h"
|
||||
#include "pttlistener.h"
|
||||
|
||||
#include <api/callmodel.h>
|
||||
#include <api/callparticipantsmodel.h>
|
||||
|
@ -45,19 +45,15 @@ CallAdapter::CallAdapter(AppSettingsManager* settingsManager,
|
|||
: QmlAdapterBase(instance, parent)
|
||||
, systemTray_(systemTray)
|
||||
, callInformationListModel_(std::make_unique<CallInformationListModel>())
|
||||
, listener_(new PTTListener(settingsManager, this))
|
||||
{
|
||||
// Expose the Push-to-talk listener to QML as a singleton
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, listener_, "PttListener");
|
||||
// Get the PTTListener instance.
|
||||
listener_ = qApp->property("PTTListener").value<PTTListener*>();
|
||||
|
||||
set_callInformationList(QVariant::fromValue(callInformationListModel_.get()));
|
||||
|
||||
timer = new QTimer(this);
|
||||
connect(timer, &QTimer::timeout, this, &CallAdapter::updateAdvancedInformation);
|
||||
|
||||
overlayModel_.reset(new CallOverlayModel(lrcInstance_, listener_, this));
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, overlayModel_.get(), "CallOverlayModel");
|
||||
|
||||
accountId_ = lrcInstance_->get_currentAccountId();
|
||||
connectCallModel(accountId_);
|
||||
|
||||
|
|
|
@ -23,32 +23,34 @@
|
|||
#include "lrcinstance.h"
|
||||
#include "qmladapterbase.h"
|
||||
#include "screensaver.h"
|
||||
#include "calloverlaymodel.h"
|
||||
|
||||
#ifdef HAVE_GLOBAL_PTT
|
||||
#include "pttlistener.h"
|
||||
#endif
|
||||
#include "callInformationListModel.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
#include "callInformationListModel.h"
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class SystemTray;
|
||||
class AppSettingsManager;
|
||||
class PTTListener;
|
||||
|
||||
class CallAdapter final : public QmlAdapterBase
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
QML_PROPERTY(bool, hasCall)
|
||||
QML_RO_PROPERTY(QVariant, callInformationList)
|
||||
|
||||
public:
|
||||
QTimer* timer;
|
||||
enum MuteStates { UNMUTED, LOCAL_MUTED, MODERATOR_MUTED, BOTH_MUTED };
|
||||
Q_ENUM(MuteStates)
|
||||
static CallAdapter* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new CallAdapter(qApp->property("AppSettingsManager").value<AppSettingsManager*>(),
|
||||
qApp->property("SystemTray").value<SystemTray*>(),
|
||||
qApp->property("LRCInstance").value<LRCInstance*>());
|
||||
}
|
||||
|
||||
explicit CallAdapter(AppSettingsManager* settingsManager,
|
||||
SystemTray* systemTray,
|
||||
|
@ -56,7 +58,10 @@ public:
|
|||
QObject* parent = nullptr);
|
||||
~CallAdapter();
|
||||
|
||||
public:
|
||||
QTimer* timer;
|
||||
enum MuteStates { UNMUTED, LOCAL_MUTED, MODERATOR_MUTED, BOTH_MUTED };
|
||||
Q_ENUM(MuteStates)
|
||||
|
||||
Q_INVOKABLE void startTimerInformation();
|
||||
Q_INVOKABLE void stopTimerInformation();
|
||||
Q_INVOKABLE void placeAudioOnlyCall();
|
||||
|
@ -131,7 +136,6 @@ private:
|
|||
|
||||
ScreenSaver screenSaver;
|
||||
SystemTray* systemTray_;
|
||||
QScopedPointer<CallOverlayModel> overlayModel_;
|
||||
VectorString currentConfSubcalls_;
|
||||
std::unique_ptr<CallInformationListModel> callInformationListModel_;
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
#include "lrcinstance.h"
|
||||
#include "qtutils.h"
|
||||
#include "mainapplication.h"
|
||||
|
||||
#include "pttlistener.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
|
|
@ -37,7 +37,7 @@ BaseModalDialog {
|
|||
button2Role: DialogButtonBox.RejectRole
|
||||
button1.onClicked: {
|
||||
if (!(pressedKey === Qt.Key_unknown)){
|
||||
PttListener.setPttKey(pressedKey);
|
||||
PTTListener.setPttKey(pressedKey);
|
||||
choiceMade(pressedKey);
|
||||
}
|
||||
close();
|
||||
|
@ -102,7 +102,7 @@ BaseModalDialog {
|
|||
id: keyItem
|
||||
|
||||
Keys.onPressed: (event)=>{
|
||||
keyLabel.text = PttListener.keyToString(event.key);
|
||||
keyLabel.text = PTTListener.keyToString(event.key);
|
||||
pressedKey = event.key;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,10 +126,6 @@ ConnectionInfoListModel::roleNames() const
|
|||
void
|
||||
ConnectionInfoListModel::update()
|
||||
{
|
||||
const auto accountId = lrcInstance_->get_currentAccountId();
|
||||
if (accountId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
aggregateData();
|
||||
}
|
||||
|
||||
|
@ -224,4 +220,4 @@ ConnectionInfoListModel::resetData()
|
|||
peerIds_.clear();
|
||||
peerData_.clear();
|
||||
endResetModel();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,8 +41,10 @@ enum Role {
|
|||
Q_ENUM_NS(Role)
|
||||
} // namespace ConnectionInfoList
|
||||
|
||||
class ConnectionInfoListModel : public AbstractListModelBase
|
||||
class ConnectionInfoListModel final : public AbstractListModelBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConnectionInfoListModel(LRCInstance* instance, QObject* parent = nullptr);
|
||||
|
||||
|
@ -56,7 +58,6 @@ private:
|
|||
using Role = ConnectionInfoList::Role;
|
||||
|
||||
VectorMapStringString connectionInfoList_;
|
||||
|
||||
QVector<QString> peerIds_;
|
||||
QMap<QString, QMap<QString, QMap<QString, QVariant>>> peerData_;
|
||||
void aggregateData();
|
||||
|
|
|
@ -21,16 +21,10 @@
|
|||
#include "contactadapter.h"
|
||||
|
||||
#include "lrcinstance.h"
|
||||
#include "qmlregister.h"
|
||||
|
||||
ContactAdapter::ContactAdapter(LRCInstance* instance, QObject* parent)
|
||||
: QmlAdapterBase(instance, parent)
|
||||
, connectionInfoListModel_(new ConnectionInfoListModel(lrcInstance_, this))
|
||||
{
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS,
|
||||
connectionInfoListModel_.get(),
|
||||
"ConnectionInfoListModel");
|
||||
|
||||
selectableProxyModel_.reset(new SelectableProxyModel(this));
|
||||
if (lrcInstance_) {
|
||||
connect(lrcInstance_,
|
||||
|
@ -252,12 +246,6 @@ ContactAdapter::removeContact(const QString& peerUri, bool banContact)
|
|||
accInfo.contactModel->removeContact(peerUri, banContact);
|
||||
}
|
||||
|
||||
void
|
||||
ContactAdapter::updateConnectionInfo()
|
||||
{
|
||||
connectionInfoListModel_->update();
|
||||
}
|
||||
|
||||
void
|
||||
ContactAdapter::connectSignals()
|
||||
{
|
||||
|
|
|
@ -20,12 +20,12 @@
|
|||
|
||||
#include "qmladapterbase.h"
|
||||
#include "smartlistmodel.h"
|
||||
#include "conversationlistmodel.h"
|
||||
#include "connectioninfolistmodel.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QString>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class LRCInstance;
|
||||
|
||||
|
@ -80,8 +80,14 @@ private:
|
|||
class ContactAdapter final : public QmlAdapterBase
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
public:
|
||||
static ContactAdapter* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new ContactAdapter(qApp->property("LRCInstance").value<LRCInstance*>());
|
||||
}
|
||||
|
||||
explicit ContactAdapter(LRCInstance* instance, QObject* parent = nullptr);
|
||||
~ContactAdapter() = default;
|
||||
|
||||
|
@ -91,7 +97,6 @@ public:
|
|||
Q_INVOKABLE void setSearchFilter(const QString& filter);
|
||||
Q_INVOKABLE void contactSelected(int index);
|
||||
Q_INVOKABLE void removeContact(const QString& peerUri, bool banContact);
|
||||
Q_INVOKABLE void updateConnectionInfo();
|
||||
|
||||
void connectSignals();
|
||||
|
||||
|
@ -106,7 +111,6 @@ private:
|
|||
SmartListModel::Type listModeltype_;
|
||||
QScopedPointer<SmartListModel> smartListModel_;
|
||||
QScopedPointer<SelectableProxyModel> selectableProxyModel_;
|
||||
QScopedPointer<ConnectionInfoListModel> connectionInfoListModel_;
|
||||
|
||||
QStringList defaultModerators_;
|
||||
|
||||
|
|
|
@ -55,10 +55,15 @@ ConversationListModel::ConversationListModel(LRCInstance* instance, QObject* par
|
|||
&ConversationListModel::endRemoveRows,
|
||||
Qt::DirectConnection);
|
||||
|
||||
connect(model_, &ConversationModel::dataChanged, this, [this](int position) {
|
||||
const auto index = createIndex(position, 0);
|
||||
Q_EMIT ConversationListModel::dataChanged(index, index);
|
||||
}, Qt::QueuedConnection);
|
||||
connect(
|
||||
model_,
|
||||
&ConversationModel::dataChanged,
|
||||
this,
|
||||
[this](int position) {
|
||||
const auto index = createIndex(position, 0);
|
||||
Q_EMIT ConversationListModel::dataChanged(index, index);
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
#include "qmlregister.h"
|
||||
#include "qtutils.h"
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include "namedirectory.h"
|
||||
#endif
|
||||
|
||||
#include <QApplication>
|
||||
#include <QJsonObject>
|
||||
|
@ -33,18 +35,21 @@ using namespace lrc::api;
|
|||
|
||||
ConversationsAdapter::ConversationsAdapter(SystemTray* systemTray,
|
||||
LRCInstance* instance,
|
||||
ConversationListProxyModel* convProxyModel,
|
||||
SelectableListProxyModel* searchProxyModel,
|
||||
QObject* parent)
|
||||
: QmlAdapterBase(instance, parent)
|
||||
, systemTray_(systemTray)
|
||||
, convSrcModel_(new ConversationListModel(lrcInstance_))
|
||||
, convModel_(new ConversationListProxyModel(convSrcModel_.get()))
|
||||
, convModel_(convProxyModel)
|
||||
, searchSrcModel_(new SearchResultsListModel(lrcInstance_))
|
||||
, searchModel_(new SelectableListProxyModel(searchSrcModel_.get()))
|
||||
, searchModel_(searchProxyModel)
|
||||
{
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, convModel_.get(), "ConversationListModel");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, searchModel_.get(), "SearchResultsListModel");
|
||||
convModel_->bindSourceModel(convSrcModel_.get());
|
||||
searchModel_->bindSourceModel(searchSrcModel_.get());
|
||||
|
||||
new SelectableListProxyGroupModel({convModel_.data(), searchModel_.data()}, this);
|
||||
set_convListProxyModel(QVariant::fromValue(convModel_));
|
||||
set_searchListProxyModel(QVariant::fromValue(searchModel_));
|
||||
|
||||
// this will trigger when the invite filter tab is selected
|
||||
connect(this, &ConversationsAdapter::filterRequestsChanged, [this]() {
|
||||
|
@ -112,32 +117,27 @@ ConversationsAdapter::ConversationsAdapter(SystemTray* systemTray,
|
|||
connect(&lrcInstance_->behaviorController(),
|
||||
&BehaviorController::newUnreadInteraction,
|
||||
this,
|
||||
&ConversationsAdapter::onNewUnreadInteraction,
|
||||
Qt::UniqueConnection);
|
||||
&ConversationsAdapter::onNewUnreadInteraction);
|
||||
|
||||
connect(&lrcInstance_->behaviorController(),
|
||||
&BehaviorController::newReadInteraction,
|
||||
this,
|
||||
&ConversationsAdapter::onNewReadInteraction,
|
||||
Qt::UniqueConnection);
|
||||
&ConversationsAdapter::onNewReadInteraction);
|
||||
|
||||
connect(&lrcInstance_->behaviorController(),
|
||||
&BehaviorController::newTrustRequest,
|
||||
this,
|
||||
&ConversationsAdapter::onNewTrustRequest,
|
||||
Qt::UniqueConnection);
|
||||
&ConversationsAdapter::onNewTrustRequest);
|
||||
|
||||
connect(&lrcInstance_->behaviorController(),
|
||||
&BehaviorController::trustRequestTreated,
|
||||
this,
|
||||
&ConversationsAdapter::onTrustRequestTreated,
|
||||
Qt::UniqueConnection);
|
||||
&ConversationsAdapter::onTrustRequestTreated);
|
||||
|
||||
connect(lrcInstance_,
|
||||
&LRCInstance::currentAccountIdChanged,
|
||||
this,
|
||||
&ConversationsAdapter::onCurrentAccountIdChanged,
|
||||
Qt::UniqueConnection);
|
||||
&ConversationsAdapter::onCurrentAccountIdChanged);
|
||||
|
||||
connectConversationModel();
|
||||
}
|
||||
|
@ -168,7 +168,6 @@ ConversationsAdapter::onNewUnreadInteraction(const QString& accountId,
|
|||
if (interaction.authorUri == accountInfo.profileInfo.uri)
|
||||
return;
|
||||
auto from = accountInfo.contactModel->bestNameForContact(interaction.authorUri);
|
||||
auto to = lrcInstance_->accountModel().bestNameForAccount(accountId);
|
||||
auto body_ = interaction.body;
|
||||
|
||||
if (interaction.type == interaction::Type::DATA_TRANSFER) {
|
||||
|
@ -180,6 +179,7 @@ ConversationsAdapter::onNewUnreadInteraction(const QString& accountId,
|
|||
if (preferences["ignoreNotifications"] == "true")
|
||||
return;
|
||||
#ifdef Q_OS_LINUX
|
||||
auto to = lrcInstance_->accountModel().bestNameForAccount(accountId);
|
||||
auto contactPhoto = Utils::contactPhoto(lrcInstance_,
|
||||
interaction.authorUri,
|
||||
QSize(50, 50),
|
||||
|
@ -599,75 +599,49 @@ void
|
|||
ConversationsAdapter::connectConversationModel()
|
||||
{
|
||||
// Signal connections
|
||||
auto currentConversationModel = lrcInstance_->getCurrentConversationModel();
|
||||
if (currentConversationModel == nullptr) {
|
||||
auto model = lrcInstance_->getCurrentConversationModel();
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
|
||||
QObject::connect(currentConversationModel,
|
||||
&ConversationModel::modelChanged,
|
||||
this,
|
||||
&ConversationsAdapter::onModelChanged,
|
||||
Qt::UniqueConnection);
|
||||
auto connectObjectSignal = [this](auto obj, auto signal, auto slot) {
|
||||
connect(obj, signal, this, slot, Qt::UniqueConnection);
|
||||
};
|
||||
|
||||
QObject::connect(lrcInstance_->getCurrentContactModel(),
|
||||
&ContactModel::profileUpdated,
|
||||
this,
|
||||
&ConversationsAdapter::onProfileUpdated,
|
||||
Qt::UniqueConnection);
|
||||
connectObjectSignal(model,
|
||||
&ConversationModel::modelChanged,
|
||||
&ConversationsAdapter::onModelChanged);
|
||||
connectObjectSignal(model,
|
||||
&ConversationModel::profileUpdated,
|
||||
&ConversationsAdapter::onProfileUpdated);
|
||||
connectObjectSignal(model,
|
||||
&ConversationModel::conversationUpdated,
|
||||
&ConversationsAdapter::onConversationUpdated);
|
||||
connectObjectSignal(model,
|
||||
&ConversationModel::conversationRemoved,
|
||||
&ConversationsAdapter::onConversationRemoved);
|
||||
connectObjectSignal(model,
|
||||
&ConversationModel::filterChanged,
|
||||
&ConversationsAdapter::onFilterChanged);
|
||||
connectObjectSignal(model,
|
||||
&ConversationModel::conversationCleared,
|
||||
&ConversationsAdapter::onConversationCleared);
|
||||
connectObjectSignal(model,
|
||||
&ConversationModel::searchStatusChanged,
|
||||
&ConversationsAdapter::onSearchStatusChanged);
|
||||
connectObjectSignal(model,
|
||||
&ConversationModel::searchResultUpdated,
|
||||
&ConversationsAdapter::onSearchResultUpdated);
|
||||
connectObjectSignal(model,
|
||||
&ConversationModel::searchResultEnded,
|
||||
&ConversationsAdapter::onSearchResultEnded);
|
||||
connectObjectSignal(model,
|
||||
&ConversationModel::conversationReady,
|
||||
&ConversationsAdapter::onConversationReady);
|
||||
|
||||
QObject::connect(currentConversationModel,
|
||||
&ConversationModel::conversationUpdated,
|
||||
this,
|
||||
&ConversationsAdapter::onConversationUpdated,
|
||||
Qt::UniqueConnection);
|
||||
QObject::connect(currentConversationModel,
|
||||
&ConversationModel::conversationRemoved,
|
||||
this,
|
||||
&ConversationsAdapter::onConversationRemoved,
|
||||
Qt::UniqueConnection);
|
||||
|
||||
QObject::connect(currentConversationModel,
|
||||
&ConversationModel::filterChanged,
|
||||
this,
|
||||
&ConversationsAdapter::onFilterChanged,
|
||||
Qt::UniqueConnection);
|
||||
|
||||
QObject::connect(currentConversationModel,
|
||||
&ConversationModel::conversationCleared,
|
||||
this,
|
||||
&ConversationsAdapter::onConversationCleared,
|
||||
Qt::UniqueConnection);
|
||||
|
||||
QObject::connect(currentConversationModel,
|
||||
&ConversationModel::searchStatusChanged,
|
||||
this,
|
||||
&ConversationsAdapter::onSearchStatusChanged,
|
||||
Qt::UniqueConnection);
|
||||
|
||||
QObject::connect(currentConversationModel,
|
||||
&ConversationModel::searchResultUpdated,
|
||||
this,
|
||||
&ConversationsAdapter::onSearchResultUpdated,
|
||||
Qt::UniqueConnection);
|
||||
|
||||
QObject::connect(currentConversationModel,
|
||||
&ConversationModel::searchResultEnded,
|
||||
this,
|
||||
&ConversationsAdapter::onSearchResultEnded,
|
||||
Qt::UniqueConnection);
|
||||
|
||||
QObject::connect(currentConversationModel,
|
||||
&ConversationModel::conversationReady,
|
||||
this,
|
||||
&ConversationsAdapter::onConversationReady,
|
||||
Qt::UniqueConnection);
|
||||
|
||||
QObject::connect(lrcInstance_->getCurrentContactModel(),
|
||||
&ContactModel::bannedStatusChanged,
|
||||
this,
|
||||
&ConversationsAdapter::onBannedStatusChanged,
|
||||
Qt::UniqueConnection);
|
||||
connectObjectSignal(lrcInstance_->getCurrentContactModel(),
|
||||
&ContactModel::bannedStatusChanged,
|
||||
&ConversationsAdapter::onBannedStatusChanged);
|
||||
|
||||
convSrcModel_.reset(new ConversationListModel(lrcInstance_));
|
||||
convModel_->bindSourceModel(convSrcModel_.get());
|
||||
|
|
|
@ -26,19 +26,36 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class SystemTray;
|
||||
|
||||
class ConversationsAdapter final : public QmlAdapterBase
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
QML_PROPERTY(bool, filterRequests)
|
||||
QML_PROPERTY(int, totalUnreadMessageCount)
|
||||
QML_PROPERTY(int, pendingRequestCount)
|
||||
QML_RO_PROPERTY(QVariant, convListProxyModel)
|
||||
QML_RO_PROPERTY(QVariant, searchListProxyModel)
|
||||
|
||||
public:
|
||||
static ConversationsAdapter* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new ConversationsAdapter(
|
||||
qApp->property("SystemTray").value<SystemTray*>(),
|
||||
qApp->property("LRCInstance").value<LRCInstance*>(),
|
||||
qApp->property("ConvListProxyModel").value<ConversationListProxyModel*>(),
|
||||
qApp->property("ConvSearchListProxyModel").value<SelectableListProxyModel*>());
|
||||
}
|
||||
|
||||
explicit ConversationsAdapter(SystemTray* systemTray,
|
||||
LRCInstance* instance,
|
||||
ConversationListProxyModel* convProxyModel,
|
||||
SelectableListProxyModel* searchProxyModel,
|
||||
QObject* parent = nullptr);
|
||||
~ConversationsAdapter() = default;
|
||||
|
||||
|
@ -46,9 +63,9 @@ public:
|
|||
void connectConversationModel();
|
||||
|
||||
Q_INVOKABLE QString createSwarm(const QString& title,
|
||||
const QString& description,
|
||||
const QString& avatar,
|
||||
const VectorString& participants);
|
||||
const QString& description,
|
||||
const QString& avatar,
|
||||
const VectorString& participants);
|
||||
Q_INVOKABLE void setFilter(const QString& filterString);
|
||||
Q_INVOKABLE void setFilterAndSelect(const QString& filterString);
|
||||
Q_INVOKABLE void ignoreFiltering(const QVariant& hightlighted);
|
||||
|
@ -107,9 +124,9 @@ private:
|
|||
SystemTray* systemTray_;
|
||||
|
||||
QScopedPointer<ConversationListModel> convSrcModel_;
|
||||
QScopedPointer<ConversationListProxyModel> convModel_;
|
||||
ConversationListProxyModel* convModel_;
|
||||
QScopedPointer<SearchResultsListModel> searchSrcModel_;
|
||||
QScopedPointer<SelectableListProxyModel> searchModel_;
|
||||
SelectableListProxyModel* searchModel_;
|
||||
|
||||
std::atomic_bool selectFirst_ {false};
|
||||
};
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
#define ACCOUNT_CONFIG_SETTINGS_PROPERTY_BASE(type, prop) \
|
||||
PROPERTY_GETTER_BASE(type, prop) \
|
||||
|
@ -97,7 +99,7 @@ private: \
|
|||
class CurrentAccount final : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
// Basic settings
|
||||
QML_SINGLETON
|
||||
|
||||
QML_RO_PROPERTY(QString, id)
|
||||
QML_RO_PROPERTY(QString, uri)
|
||||
|
@ -194,6 +196,12 @@ class CurrentAccount final : public QObject
|
|||
QML_ACCOUNT_CONFIG_SETTINGS_PROPERTY(QJsonObject, uiCustomization)
|
||||
|
||||
public:
|
||||
static CurrentAccount* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new CurrentAccount(qApp->property("LRCInstance").value<LRCInstance*>(),
|
||||
qApp->property("AppSettingsManager").value<AppSettingsManager*>());
|
||||
}
|
||||
|
||||
explicit CurrentAccount(LRCInstance* lrcInstance,
|
||||
AppSettingsManager* settingsManager,
|
||||
QObject* parent = nullptr);
|
||||
|
|
|
@ -58,8 +58,6 @@ CurrentAccountToMigrate::CurrentAccountToMigrate(LRCInstance* instance, QObject*
|
|||
&CurrentAccountToMigrate::slotAccountRemoved);
|
||||
}
|
||||
|
||||
CurrentAccountToMigrate::~CurrentAccountToMigrate() {}
|
||||
|
||||
void
|
||||
CurrentAccountToMigrate::removeCurrentAccountToMigrate()
|
||||
{
|
||||
|
@ -133,4 +131,4 @@ CurrentAccountToMigrate::slotAccountRemoved(const QString& accountId)
|
|||
Q_EMIT allMigrationsFinished();
|
||||
else
|
||||
Q_EMIT currentAccountToMigrateRemoved();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,15 +19,19 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "qtutils.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class LRCInstance;
|
||||
|
||||
class CurrentAccountToMigrate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
QML_RO_PROPERTY(int, accountToMigrateListSize)
|
||||
QML_RO_PROPERTY(QString, accountId)
|
||||
QML_RO_PROPERTY(QString, managerUsername)
|
||||
|
@ -36,8 +40,13 @@ class CurrentAccountToMigrate : public QObject
|
|||
QML_RO_PROPERTY(QString, alias)
|
||||
|
||||
public:
|
||||
static CurrentAccountToMigrate* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new CurrentAccountToMigrate(qApp->property("LRCInstance").value<LRCInstance*>());
|
||||
}
|
||||
|
||||
explicit CurrentAccountToMigrate(LRCInstance* lrcInstance, QObject* parent = nullptr);
|
||||
~CurrentAccountToMigrate();
|
||||
~CurrentAccountToMigrate() = default;
|
||||
|
||||
Q_INVOKABLE void removeCurrentAccountToMigrate();
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
*/
|
||||
|
||||
#include "currentcall.h"
|
||||
#include "qmlregister.h"
|
||||
|
||||
#include "callparticipantsmodel.h"
|
||||
|
||||
#include <api/callparticipantsmodel.h>
|
||||
#include <api/devicemodel.h>
|
||||
|
@ -25,8 +26,7 @@ CurrentCall::CurrentCall(LRCInstance* lrcInstance, QObject* parent)
|
|||
: QObject(parent)
|
||||
, lrcInstance_(lrcInstance)
|
||||
{
|
||||
participantsModel_.reset(new CallParticipantsModel(lrcInstance_, this));
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, participantsModel_.get(), "CallParticipantsModel");
|
||||
participantsModel_ = qApp->property("CallParticipantsModel").value<CallParticipantsModel*>();
|
||||
|
||||
connect(lrcInstance_,
|
||||
&LRCInstance::currentAccountIdChanged,
|
||||
|
|
|
@ -19,14 +19,18 @@
|
|||
|
||||
#include "lrcinstance.h"
|
||||
#include "qtutils.h"
|
||||
#include "callparticipantsmodel.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class CallParticipantsModel;
|
||||
|
||||
class CurrentCall final : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
QML_RO_PROPERTY(QString, id)
|
||||
QML_RO_PROPERTY(QStringList, uris)
|
||||
|
@ -55,6 +59,11 @@ class CurrentCall final : public QObject
|
|||
QML_PROPERTY(bool, flipSelf)
|
||||
|
||||
public:
|
||||
static CurrentCall* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new CurrentCall(qApp->property("LRCInstance").value<LRCInstance*>());
|
||||
}
|
||||
|
||||
explicit CurrentCall(LRCInstance* lrcInstance, QObject* parent = nullptr);
|
||||
~CurrentCall() = default;
|
||||
Q_INVOKABLE QVariantList getConferencesInfos() const;
|
||||
|
@ -85,5 +94,5 @@ private Q_SLOTS:
|
|||
|
||||
private:
|
||||
LRCInstance* lrcInstance_;
|
||||
QScopedPointer<CallParticipantsModel> participantsModel_;
|
||||
CallParticipantsModel* participantsModel_;
|
||||
};
|
||||
|
|
|
@ -24,7 +24,9 @@ CurrentConversation::CurrentConversation(LRCInstance* lrcInstance, QObject* pare
|
|||
: QObject(parent)
|
||||
, lrcInstance_(lrcInstance)
|
||||
{
|
||||
uris_ = new CurrentConversationMembers(lrcInstance, this);
|
||||
membersModel_ = new CurrentConversationMembers(lrcInstance, this);
|
||||
set_members(QVariant::fromValue(membersModel_));
|
||||
|
||||
// whenever the account changes, reconnect the new conversation model
|
||||
// for updates to the conversation and call state/id
|
||||
connect(lrcInstance_,
|
||||
|
@ -55,7 +57,7 @@ CurrentConversation::updateData()
|
|||
// If the conversation is empty, clear the id and return.
|
||||
if (convId.isEmpty()) {
|
||||
set_id();
|
||||
uris_->setMembers({}, {}, {});
|
||||
membersModel_->setMembers({}, {}, {});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -95,7 +97,7 @@ CurrentConversation::updateData()
|
|||
for (const auto& banned : bannedUris)
|
||||
uris.push_back(banned);
|
||||
}
|
||||
uris_->setMembers(accountId, convId, uris);
|
||||
membersModel_->setMembers(accountId, convId, uris);
|
||||
set_isSwarm(convInfo.isSwarm());
|
||||
set_isLegacy(convInfo.isLegacy());
|
||||
set_isCoreDialog(convInfo.isCoreDialog());
|
||||
|
@ -202,12 +204,6 @@ CurrentConversation::setInfo(const QString& key, const QString& value)
|
|||
accInfo.conversationModel->updateConversationInfos(convId, infos);
|
||||
}
|
||||
|
||||
CurrentConversationMembers*
|
||||
CurrentConversation::uris() const
|
||||
{
|
||||
return uris_;
|
||||
}
|
||||
|
||||
void
|
||||
CurrentConversation::onConversationUpdated(const QString& convId)
|
||||
{
|
||||
|
@ -266,16 +262,22 @@ CurrentConversation::updateConversationPreferences(const QString& convId)
|
|||
void
|
||||
CurrentConversation::connectModel()
|
||||
{
|
||||
uris_->setMembers({}, {}, {});
|
||||
membersModel_->setMembers({}, {}, {});
|
||||
auto convModel = lrcInstance_->getCurrentConversationModel();
|
||||
if (!convModel)
|
||||
return;
|
||||
|
||||
connect(lrcInstance_->getCurrentConversationModel(),
|
||||
&ConversationModel::conversationUpdated,
|
||||
this,
|
||||
&CurrentConversation::onConversationUpdated,
|
||||
Qt::UniqueConnection);
|
||||
auto connectObjectSignal = [this](auto obj, auto signal, auto slot) {
|
||||
connect(obj, signal, this, slot, Qt::UniqueConnection);
|
||||
};
|
||||
|
||||
connectObjectSignal(convModel,
|
||||
&ConversationModel::conversationUpdated,
|
||||
&CurrentConversation::onConversationUpdated);
|
||||
connectObjectSignal(convModel,
|
||||
&ConversationModel::profileUpdated,
|
||||
&CurrentConversation::updateProfile);
|
||||
|
||||
connect(lrcInstance_->getCurrentConversationModel(),
|
||||
&ConversationModel::profileUpdated,
|
||||
this,
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
// an adapter object to expose a conversation::Info struct
|
||||
// as a group of observable properties
|
||||
|
@ -30,6 +32,8 @@
|
|||
class CurrentConversation final : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
QML_PROPERTY(QString, id)
|
||||
QML_PROPERTY(QString, title)
|
||||
QML_PROPERTY(QString, description)
|
||||
|
@ -56,10 +60,17 @@ class CurrentConversation final : public QObject
|
|||
QML_PROPERTY(QStringList, backendErrors)
|
||||
QML_PROPERTY(QString, lastSelfMessageId)
|
||||
QML_RO_PROPERTY(bool, hasCall)
|
||||
QML_RO_PROPERTY(QVariant, members)
|
||||
|
||||
public:
|
||||
static CurrentConversation* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new CurrentConversation(qApp->property("LRCInstance").value<LRCInstance*>());
|
||||
}
|
||||
|
||||
explicit CurrentConversation(LRCInstance* lrcInstance, QObject* parent = nullptr);
|
||||
~CurrentConversation() = default;
|
||||
|
||||
Q_INVOKABLE void scrollToMsg(const QString& msgId);
|
||||
Q_INVOKABLE void setPreference(const QString& key, const QString& value);
|
||||
Q_INVOKABLE QString getPreference(const QString& key) const;
|
||||
|
@ -88,7 +99,7 @@ Q_SIGNALS:
|
|||
|
||||
private:
|
||||
LRCInstance* lrcInstance_;
|
||||
CurrentConversationMembers* uris_;
|
||||
CurrentConversationMembers* membersModel_;
|
||||
|
||||
void connectModel();
|
||||
};
|
||||
|
|
|
@ -41,7 +41,7 @@ Q_ENUM_NS(Role)
|
|||
class CurrentConversationMembers : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_PROPERTY(int, count)
|
||||
QML_RO_PROPERTY(int, count)
|
||||
|
||||
public:
|
||||
explicit CurrentConversationMembers(LRCInstance* lrcInstance, QObject* parent = nullptr);
|
||||
|
@ -56,4 +56,4 @@ private:
|
|||
QString accountId_;
|
||||
QString convId_;
|
||||
QStringList members_;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -18,16 +18,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "networkmanager.h"
|
||||
#include "connectivitymonitor.h"
|
||||
#include "qtutils.h"
|
||||
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class ImageDownloader : public NetworkManager
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
QML_PROPERTY(QString, cachePath)
|
||||
|
||||
public:
|
||||
static ImageDownloader* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new ImageDownloader(
|
||||
qApp->property("ConnectivityMonitor").value<ConnectivityMonitor*>());
|
||||
}
|
||||
|
||||
explicit ImageDownloader(ConnectivityMonitor* cm, QObject* parent = nullptr);
|
||||
~ImageDownloader() = default;
|
||||
|
||||
// Download an image and call onDownloadImageFinished when done
|
||||
Q_INVOKABLE void downloadImage(const QUrl& url, const QString& localPath);
|
||||
|
@ -39,4 +51,4 @@ Q_SIGNALS:
|
|||
private Q_SLOTS:
|
||||
// Saves the image to the localPath and emits the appropriate signal
|
||||
void onDownloadImageFinished(const QByteArray& reply, const QString& localPath);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "connectivitymonitor.h"
|
||||
#include "systemtray.h"
|
||||
#include "videoprovider.h"
|
||||
#include "previewengine.h"
|
||||
#include "conversationlistmodel.h"
|
||||
|
||||
#include <QWKQuick/qwkquickglobal.h>
|
||||
|
||||
|
@ -42,7 +44,6 @@
|
|||
#include <QQuickWindow>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
#include <locale.h>
|
||||
#include <thread>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -188,6 +189,7 @@ MainApplication::init()
|
|||
connectivityMonitor_ = new ConnectivityMonitor(this);
|
||||
settingsManager_ = new AppSettingsManager(this);
|
||||
systemTray_ = new SystemTray(settingsManager_, this);
|
||||
previewEngine_ = new PreviewEngine(connectivityMonitor_, this);
|
||||
|
||||
// These should should be QueuedConnection to ensure that the
|
||||
// they are executed after the QML engine has been initialized,
|
||||
|
@ -407,6 +409,7 @@ MainApplication::initQmlLayer()
|
|||
systemTray_,
|
||||
settingsManager_,
|
||||
connectivityMonitor_,
|
||||
previewEngine_,
|
||||
&screenInfo_,
|
||||
this);
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
class ConnectivityMonitor;
|
||||
class AppSettingsManager;
|
||||
class SystemTray;
|
||||
class PreviewEngine;
|
||||
|
||||
// Provides information about the screen the app is displayed on
|
||||
class ScreenInfo : public QObject
|
||||
|
@ -120,6 +121,7 @@ private:
|
|||
ConnectivityMonitor* connectivityMonitor_;
|
||||
SystemTray* systemTray_;
|
||||
AppSettingsManager* settingsManager_;
|
||||
PreviewEngine* previewEngine_;
|
||||
|
||||
ScreenInfo screenInfo_;
|
||||
};
|
||||
|
|
|
@ -57,8 +57,8 @@ Rectangle {
|
|||
Layout.leftMargin: 4
|
||||
Layout.rightMargin: 4
|
||||
|
||||
// Reset the model if visible or the CurrentConversationMembers.count changes (0 or greater)
|
||||
model: visible && CurrentConversationMembers.count >= 0 ? ContactAdapter.getContactSelectableModel(type) : null
|
||||
// Reset the model if visible or the current conv member count changes (0 or greater)
|
||||
model: visible && CurrentConversation.members.count >= 0 ? ContactAdapter.getContactSelectableModel(type) : null
|
||||
|
||||
delegate: ContactPickerItemDelegate {
|
||||
id: contactPickerItemDelegate
|
||||
|
|
|
@ -65,12 +65,12 @@ StackLayout {
|
|||
}
|
||||
|
||||
Connections {
|
||||
target: CurrentConversationMembers
|
||||
target: CurrentConversation.members
|
||||
|
||||
function onCountChanged() {
|
||||
// Close the panel if there are 8 or more members in the
|
||||
// conversation AND the "Add Member" panel is currently open.
|
||||
if (CurrentConversationMembers.count >= 8 && isOpen(ChatView.AddMemberPanel)) {
|
||||
if (CurrentConversation.members.count >= 8 && isOpen(ChatView.AddMemberPanel)) {
|
||||
closePanel();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,28 +70,6 @@ JamiListView {
|
|||
|
||||
onCountChanged: positionViewAtBeginning()
|
||||
|
||||
add: Transition {
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 0
|
||||
to: 1.0
|
||||
duration: JamiTheme.smartListTransitionDuration
|
||||
}
|
||||
}
|
||||
|
||||
displaced: Transition {
|
||||
NumberAnimation {
|
||||
properties: "x,y"
|
||||
easing.type: Easing.OutCubic
|
||||
duration: JamiTheme.smartListTransitionDuration
|
||||
}
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
to: 1.0
|
||||
duration: JamiTheme.smartListTransitionDuration * (1 - from)
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
easing.type: Easing.OutCubic
|
||||
|
|
|
@ -57,7 +57,7 @@ Popup {
|
|||
if (isCall) {
|
||||
pluginhandlerPickerListView.model = PluginAdapter.getMediaHandlerSelectableModel(CurrentCall.id);
|
||||
} else {
|
||||
var peerId = CurrentConversation.isSwarm ? CurrentConversation.id : CurrentConversationMembers[0];
|
||||
var peerId = CurrentConversation.isSwarm ? CurrentConversation.id : CurrentConversation.members[0];
|
||||
pluginhandlerPickerListView.model = PluginAdapter.getChatHandlerSelectableModel(LRCInstance.currentAccountId, peerId);
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ Popup {
|
|||
pluginhandlerPickerListView.model = PluginAdapter.getMediaHandlerSelectableModel(CurrentCall.id);
|
||||
} else {
|
||||
var accountId = LRCInstance.currentAccountId;
|
||||
var peerId = CurrentConversation.isSwarm ? CurrentConversation.id : CurrentConversationMembers[0];
|
||||
var peerId = CurrentConversation.isSwarm ? CurrentConversation.id : CurrentConversation.members[0];
|
||||
PluginModel.toggleChatHandler(handlerId, accountId, peerId, !isLoaded);
|
||||
pluginhandlerPickerListView.model = PluginAdapter.getChatHandlerSelectableModel(accountId, peerId);
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ Popup {
|
|||
if (isCall) {
|
||||
return PluginAdapter.getMediaHandlerSelectableModel(CurrentCall.id);
|
||||
} else {
|
||||
var peerId = CurrentConversation.isSwarm ? CurrentConversation.id : CurrentConversationMembers[0];
|
||||
var peerId = CurrentConversation.isSwarm ? CurrentConversation.id : CurrentConversation.members[0];
|
||||
return PluginAdapter.getChatHandlerSelectableModel(LRCInstance.currentAccountId, peerId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -378,7 +378,7 @@ SidePanelBase {
|
|||
return parent.height;
|
||||
}
|
||||
|
||||
model: SearchResultsListModel
|
||||
model: ConversationsAdapter.searchListProxyModel
|
||||
headerLabel: JamiStrings.searchResults
|
||||
headerVisible: true
|
||||
}
|
||||
|
@ -389,7 +389,7 @@ SidePanelBase {
|
|||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
model: ConversationListModel
|
||||
model: ConversationsAdapter.convListProxyModel
|
||||
headerLabel: JamiStrings.conversations
|
||||
headerVisible: count && searchResultsListView.visible
|
||||
}
|
||||
|
@ -411,7 +411,7 @@ SidePanelBase {
|
|||
Layout.preferredWidth: parent.width
|
||||
Layout.fillHeight: true
|
||||
|
||||
model: ConversationListModel
|
||||
model: ConversationsAdapter.convListProxyModel
|
||||
delegate: SmartListItemDelegate {
|
||||
interactive: false
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ Rectangle {
|
|||
objectName: "members"
|
||||
visible: !CurrentConversation.isCoreDialog
|
||||
labelText: {
|
||||
var membersNb = CurrentConversationMembers.count;
|
||||
var membersNb = CurrentConversation.members.count;
|
||||
if (membersNb > 1)
|
||||
return JamiStrings.members.arg(membersNb);
|
||||
return JamiStrings.member;
|
||||
|
@ -581,7 +581,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
model: CurrentConversationMembers
|
||||
model: CurrentConversation.members
|
||||
delegate: ItemDelegate {
|
||||
id: member
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "appsettingsmanager.h"
|
||||
#include "qtutils.h"
|
||||
#include "messageparser.h"
|
||||
#include "previewengine.h"
|
||||
|
||||
#include <api/datatransfermodel.h>
|
||||
|
||||
|
|
|
@ -20,16 +20,18 @@
|
|||
|
||||
#include "lrcinstance.h"
|
||||
#include "qmladapterbase.h"
|
||||
|
||||
#include "previewengine.h"
|
||||
#include "messageparser.h"
|
||||
#include "appsettingsmanager.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class AppSettingsManager;
|
||||
class MessageParser;
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class FilteredMsgListModel final : public QSortFilterProxyModel
|
||||
{
|
||||
|
@ -63,6 +65,8 @@ public:
|
|||
class MessagesAdapter final : public QmlAdapterBase
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
QML_RO_PROPERTY(QVariant, messageListModel)
|
||||
QML_PROPERTY(QString, replyToId)
|
||||
QML_PROPERTY(QString, editId)
|
||||
|
@ -71,23 +75,19 @@ class MessagesAdapter final : public QmlAdapterBase
|
|||
QML_PROPERTY(QString, searchbarPrompt)
|
||||
|
||||
public:
|
||||
static MessagesAdapter* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new MessagesAdapter(qApp->property("AppSettingsManager").value<AppSettingsManager*>(),
|
||||
qApp->property("PreviewEngine").value<PreviewEngine*>(),
|
||||
qApp->property("LRCInstance").value<LRCInstance*>());
|
||||
}
|
||||
|
||||
explicit MessagesAdapter(AppSettingsManager* settingsManager,
|
||||
PreviewEngine* previewEngine,
|
||||
LRCInstance* instance,
|
||||
QObject* parent = nullptr);
|
||||
~MessagesAdapter() = default;
|
||||
|
||||
Q_SIGNALS:
|
||||
void newInteraction(const QString& id, int type);
|
||||
void newMessageBarPlaceholderText(QString& placeholderText);
|
||||
void newFilePasted(QString filePath);
|
||||
void newTextPasted();
|
||||
void moreMessagesLoaded(qint32 loadingRequestId);
|
||||
void timestampUpdated();
|
||||
void fileCopied(const QString& dest);
|
||||
void messageParsed(const QString& msgId, const QString& msg);
|
||||
|
||||
protected:
|
||||
Q_INVOKABLE bool isDocument(const interaction::Type& type);
|
||||
Q_INVOKABLE void loadMoreMessages();
|
||||
Q_INVOKABLE void connectConversationModel();
|
||||
|
@ -149,6 +149,15 @@ protected:
|
|||
|
||||
inline MessageListModel* getMsgListSourceModel() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void newInteraction(const QString& id, int type);
|
||||
void newFilePasted(const QString& filePath);
|
||||
void newTextPasted();
|
||||
void moreMessagesLoaded(qint32 loadingRequestId);
|
||||
void timestampUpdated();
|
||||
void fileCopied(const QString& dest);
|
||||
void messageParsed(const QString& msgId, const QString& msg);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onNewInteraction(const QString& convUid,
|
||||
const QString& interactionId,
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
#include "networkmanager.h"
|
||||
#include "lrcinstance.h"
|
||||
#include "appsettingsmanager.h"
|
||||
#include "qmlregister.h"
|
||||
|
||||
#include "api/pluginmodel.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
@ -35,8 +36,7 @@
|
|||
|
||||
PluginAdapter::PluginAdapter(LRCInstance* instance,
|
||||
AppSettingsManager* settingsManager,
|
||||
QObject* parent,
|
||||
QString baseUrl)
|
||||
QObject* parent)
|
||||
: QmlAdapterBase(instance, parent)
|
||||
, pluginStoreListModel_(new PluginStoreListModel(instance, this))
|
||||
, pluginVersionManager_(new PluginVersionManager(instance, settingsManager, this))
|
||||
|
@ -44,8 +44,9 @@ PluginAdapter::PluginAdapter(LRCInstance* instance,
|
|||
, lrcInstance_(instance)
|
||||
, settingsManager_(settingsManager)
|
||||
{
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, pluginStoreListModel_, "PluginStoreListModel");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, pluginListModel_, "PluginListModel")
|
||||
pluginListModel_ = qApp->property("PluginListModel").value<PluginListModel*>();
|
||||
pluginStoreListModel_ = qApp->property("PluginStoreListModel").value<PluginStoreListModel*>();
|
||||
|
||||
updateHandlersListCount();
|
||||
connect(&lrcInstance_->pluginModel(),
|
||||
&lrc::api::PluginModel::modelUpdated,
|
||||
|
|
|
@ -19,33 +19,37 @@
|
|||
#pragma once
|
||||
|
||||
#include "qmladapterbase.h"
|
||||
#include "pluginlistmodel.h"
|
||||
#include "pluginhandlerlistmodel.h"
|
||||
#include "pluginlistpreferencemodel.h"
|
||||
#include "appsettingsmanager.h"
|
||||
#include "pluginversionmanager.h"
|
||||
#include "pluginstorelistmodel.h"
|
||||
#include "preferenceitemlistmodel.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QString>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class PluginVersionManager;
|
||||
class PluginListModel;
|
||||
class PluginStoreListModel;
|
||||
class PluginVersionManager;
|
||||
class AppSettingsManager;
|
||||
|
||||
class PluginAdapter final : public QmlAdapterBase
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
QML_PROPERTY(int, callMediaHandlersListCount)
|
||||
QML_PROPERTY(int, chatHandlersListCount)
|
||||
|
||||
public:
|
||||
static PluginAdapter* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new PluginAdapter(qApp->property("LRCInstance").value<LRCInstance*>(),
|
||||
qApp->property("AppSettingsManager").value<AppSettingsManager*>());
|
||||
}
|
||||
|
||||
explicit PluginAdapter(LRCInstance* instance,
|
||||
AppSettingsManager* settingsManager,
|
||||
QObject* parent = nullptr,
|
||||
QString baseUrl = "https://plugins.jami.net");
|
||||
QObject* parent = nullptr);
|
||||
~PluginAdapter() = default;
|
||||
|
||||
Q_INVOKABLE void getPluginsFromStore();
|
||||
|
@ -73,9 +77,9 @@ Q_SIGNALS:
|
|||
private:
|
||||
void updateHandlersListCount();
|
||||
|
||||
PluginListModel* pluginListModel_;
|
||||
PluginStoreListModel* pluginStoreListModel_;
|
||||
PluginVersionManager* pluginVersionManager_;
|
||||
PluginListModel* pluginListModel_;
|
||||
|
||||
std::unique_ptr<PluginHandlerListModel> pluginHandlerListModel_;
|
||||
|
||||
|
|
|
@ -27,16 +27,27 @@
|
|||
#include <QMutex>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class PositionManager : public QmlAdapterBase
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
// map of elements : map key and isUnpin
|
||||
QML_PROPERTY(QVariantMap, mapStatus)
|
||||
QML_PROPERTY(bool, mapAutoOpening)
|
||||
QML_PROPERTY(int, positionShareConvIdsCount)
|
||||
QML_PROPERTY(int, sharingUrisCount)
|
||||
public:
|
||||
static PositionManager* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new PositionManager(qApp->property("AppSettingsManager").value<AppSettingsManager*>(),
|
||||
qApp->property("SystemTray").value<SystemTray*>(),
|
||||
qApp->property("LRCInstance").value<LRCInstance*>());
|
||||
}
|
||||
|
||||
explicit PositionManager(AppSettingsManager* settingsManager,
|
||||
SystemTray* systemTray,
|
||||
LRCInstance* instance,
|
||||
|
|
|
@ -17,32 +17,72 @@
|
|||
|
||||
#include "previewengine.h"
|
||||
|
||||
#include "htmlparser.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <QThread>
|
||||
|
||||
const QRegularExpression PreviewEngine::newlineRe("\\r?\\n");
|
||||
class PreviewEngine::Parser : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Parser(QObject* parent = nullptr);
|
||||
~Parser() = default;
|
||||
|
||||
Q_SIGNAL void infoReady(const QString& id, const QVariantMap& info);
|
||||
|
||||
public:
|
||||
Q_SLOT void processHTML(const QString& id, const QString& link, const QString& data);
|
||||
|
||||
private:
|
||||
// An instance of HtmlParser used to parse HTML.
|
||||
HtmlParser* htmlParser_;
|
||||
|
||||
QString getTagContent(const QList<QString>& tags, const QString& value);
|
||||
QString getTitle(const QList<QString>& metaTags);
|
||||
QString getDescription(const QList<QString>& metaTags);
|
||||
QString getImage(const QList<QString>& metaTags);
|
||||
|
||||
static const QRegularExpression newlineRe;
|
||||
};
|
||||
|
||||
const QRegularExpression PreviewEngine::Parser::newlineRe("\\r?\\n");
|
||||
|
||||
PreviewEngine::PreviewEngine(ConnectivityMonitor* cm, QObject* parent)
|
||||
: NetworkManager(cm, parent)
|
||||
, htmlParser_(new HtmlParser(this))
|
||||
, parser_(new PreviewEngine::Parser)
|
||||
{
|
||||
// Run this object in a separate thread.
|
||||
thread_ = new QThread();
|
||||
moveToThread(thread_);
|
||||
thread_->start();
|
||||
parserThread_ = new QThread();
|
||||
parser_->moveToThread(parserThread_);
|
||||
|
||||
// Connect on a queued connection to avoid blocking caller thread.
|
||||
connect(this, &PreviewEngine::parseLink, this, &PreviewEngine::onParseLink, Qt::QueuedConnection);
|
||||
connect(this, &PreviewEngine::parseLink, this, &PreviewEngine::onParseLink);
|
||||
connect(this, &PreviewEngine::htmlReady, parser_.get(), &Parser::processHTML);
|
||||
connect(parser_.get(), &Parser::infoReady, this, &PreviewEngine::infoReady);
|
||||
|
||||
parserThread_->start();
|
||||
}
|
||||
|
||||
PreviewEngine::~PreviewEngine()
|
||||
{
|
||||
thread_->quit();
|
||||
thread_->wait();
|
||||
parserThread_->quit();
|
||||
parserThread_->wait();
|
||||
}
|
||||
|
||||
void
|
||||
PreviewEngine::onParseLink(const QString& id, const QString& link)
|
||||
{
|
||||
sendGetRequest(link,
|
||||
[this, id, link](const QByteArray& html) { Q_EMIT htmlReady(id, link, html); });
|
||||
}
|
||||
|
||||
PreviewEngine::Parser::Parser(QObject* parent)
|
||||
: QObject(parent)
|
||||
, htmlParser_(new HtmlParser(this))
|
||||
{}
|
||||
|
||||
QString
|
||||
PreviewEngine::getTagContent(const QList<QString>& tags, const QString& value)
|
||||
PreviewEngine::Parser::getTagContent(const QList<QString>& tags, const QString& value)
|
||||
{
|
||||
Q_FOREACH (auto tag, tags) {
|
||||
const QRegularExpression re("(property|name)=\"(og:|twitter:|)" + value
|
||||
|
@ -56,7 +96,7 @@ PreviewEngine::getTagContent(const QList<QString>& tags, const QString& value)
|
|||
}
|
||||
|
||||
QString
|
||||
PreviewEngine::getTitle(const QList<QString>& metaTags)
|
||||
PreviewEngine::Parser::getTitle(const QList<QString>& metaTags)
|
||||
{
|
||||
// Try with opengraph/twitter props
|
||||
QString title = getTagContent(metaTags, "title");
|
||||
|
@ -73,7 +113,7 @@ PreviewEngine::getTitle(const QList<QString>& metaTags)
|
|||
}
|
||||
|
||||
QString
|
||||
PreviewEngine::getDescription(const QList<QString>& metaTags)
|
||||
PreviewEngine::Parser::getDescription(const QList<QString>& metaTags)
|
||||
{
|
||||
// Try with og/twitter props
|
||||
QString desc = getTagContent(metaTags, "description");
|
||||
|
@ -84,7 +124,7 @@ PreviewEngine::getDescription(const QList<QString>& metaTags)
|
|||
}
|
||||
|
||||
QString
|
||||
PreviewEngine::getImage(const QList<QString>& metaTags)
|
||||
PreviewEngine::Parser::getImage(const QList<QString>& metaTags)
|
||||
{
|
||||
// Try with og/twitter props
|
||||
QString image = getTagContent(metaTags, "image");
|
||||
|
@ -101,25 +141,25 @@ PreviewEngine::getImage(const QList<QString>& metaTags)
|
|||
}
|
||||
|
||||
void
|
||||
PreviewEngine::onParseLink(const QString& messageId, const QString& link)
|
||||
PreviewEngine::Parser::processHTML(const QString& id, const QString& link, const QString& data)
|
||||
{
|
||||
sendGetRequest(QUrl(link), [this, messageId, link](const QByteArray& html) {
|
||||
htmlParser_->parseHtmlString(html);
|
||||
auto tagsNodes = htmlParser_->getTagsNodes({TidyTag_META});
|
||||
auto metaTagNodes = tagsNodes[TidyTag_META];
|
||||
QList<QString> metaTags;
|
||||
Q_FOREACH (auto tag, metaTagNodes) {
|
||||
metaTags.append(htmlParser_->getNodeText(tag));
|
||||
}
|
||||
QString domain = QUrl(link).host();
|
||||
if (domain.isEmpty()) {
|
||||
domain = link;
|
||||
}
|
||||
Q_EMIT infoReady(messageId,
|
||||
{{"title", getTitle(metaTags)},
|
||||
{"description", getDescription(metaTags)},
|
||||
{"image", getImage(metaTags)},
|
||||
{"url", link},
|
||||
{"domain", domain}});
|
||||
});
|
||||
htmlParser_->parseHtmlString(data);
|
||||
auto tagsNodes = htmlParser_->getTagsNodes({TidyTag_META});
|
||||
auto metaTagNodes = tagsNodes[TidyTag_META];
|
||||
QList<QString> metaTags;
|
||||
Q_FOREACH (auto tag, metaTagNodes) {
|
||||
metaTags.append(htmlParser_->getNodeText(tag));
|
||||
}
|
||||
QString domain = QUrl(link).host();
|
||||
if (domain.isEmpty()) {
|
||||
domain = link;
|
||||
}
|
||||
Q_EMIT infoReady(id,
|
||||
{{"title", getTitle(metaTags)},
|
||||
{"description", getDescription(metaTags)},
|
||||
{"image", getImage(metaTags)},
|
||||
{"url", link},
|
||||
{"domain", domain}});
|
||||
}
|
||||
|
||||
#include "previewengine.moc"
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
#include "networkmanager.h"
|
||||
|
||||
#include "htmlparser.h"
|
||||
|
||||
class PreviewEngine final : public NetworkManager
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -30,21 +28,14 @@ public:
|
|||
~PreviewEngine();
|
||||
|
||||
Q_SIGNALS:
|
||||
void parseLink(const QString& messageId, const QString& link);
|
||||
void infoReady(const QString& messageId, const QVariantMap& info);
|
||||
void parseLink(const QString& id, const QString& link);
|
||||
void infoReady(const QString& id, const QVariantMap& info);
|
||||
|
||||
private:
|
||||
Q_SLOT void onParseLink(const QString& messageId, const QString& link);
|
||||
Q_SLOT void onParseLink(const QString& id, const QString& link);
|
||||
Q_SIGNAL void htmlReady(const QString& id, const QString& link, const QByteArray& data);
|
||||
|
||||
// An instance of HtmlParser used to parse HTML.
|
||||
HtmlParser* htmlParser_;
|
||||
|
||||
QString getTagContent(const QList<QString>& tags, const QString& value);
|
||||
QString getTitle(const QList<QString>& metaTags);
|
||||
QString getDescription(const QList<QString>& metaTags);
|
||||
QString getImage(const QList<QString>& metaTags);
|
||||
|
||||
static const QRegularExpression newlineRe;
|
||||
|
||||
QThread* thread_;
|
||||
class Parser;
|
||||
QScopedPointer<Parser> parser_;
|
||||
QThread* parserThread_;
|
||||
};
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "positionmanager.h"
|
||||
#include "tipsmodel.h"
|
||||
#include "connectivitymonitor.h"
|
||||
#include "previewengine.h"
|
||||
#include "imagedownloader.h"
|
||||
#include "utilsadapter.h"
|
||||
#include "conversationsadapter.h"
|
||||
|
@ -36,7 +35,8 @@
|
|||
#include "currentaccount.h"
|
||||
#include "videodevices.h"
|
||||
#include "currentaccounttomigrate.h"
|
||||
|
||||
#include "pttlistener.h"
|
||||
#include "calloverlaymodel.h"
|
||||
#include "accountlistmodel.h"
|
||||
#include "mediacodeclistmodel.h"
|
||||
#include "audiodevicemodel.h"
|
||||
|
@ -47,7 +47,10 @@
|
|||
#include "smartlistmodel.h"
|
||||
#include "filestosendlistmodel.h"
|
||||
#include "callInformationListModel.h"
|
||||
#include "rendererinformationlistmodel.h"
|
||||
#include "connectioninfolistmodel.h"
|
||||
#include "callparticipantsmodel.h"
|
||||
#include "pluginlistmodel.h"
|
||||
#include "pluginstorelistmodel.h"
|
||||
|
||||
#include "qrimageprovider.h"
|
||||
#include "avatarimageprovider.h"
|
||||
|
@ -75,6 +78,7 @@
|
|||
// clang-format off
|
||||
// TODO: remove this
|
||||
#define QML_REGISTERSINGLETONTYPE_WITH_INSTANCE(T) \
|
||||
QQmlEngine::setObjectOwnership(&T::instance(), QQmlEngine::CppOwnership); \
|
||||
qmlRegisterSingletonType<T>(NS_MODELS, MODULE_VER_MAJ, MODULE_VER_MIN, #T, \
|
||||
[](QQmlEngine* e, QJSEngine* se) -> QObject* { \
|
||||
Q_UNUSED(e); Q_UNUSED(se); \
|
||||
|
@ -97,6 +101,10 @@
|
|||
MODULE_VER_MAJ, MODULE_VER_MIN, #T, \
|
||||
"Don't try to add to a qml definition of " #T);
|
||||
|
||||
#define REG_QML_SINGLETON qmlRegisterSingletonType
|
||||
#define REG_MODEL NS_MODELS, MODULE_VER_MAJ, MODULE_VER_MIN
|
||||
#define CREATE(Obj) [=](QQmlEngine*, QJSEngine*) -> QObject* { return Obj; }
|
||||
|
||||
namespace Utils {
|
||||
|
||||
/*!
|
||||
|
@ -108,65 +116,103 @@ registerTypes(QQmlEngine* engine,
|
|||
SystemTray* systemTray,
|
||||
AppSettingsManager* settingsManager,
|
||||
ConnectivityMonitor* connectivityMonitor,
|
||||
PreviewEngine* previewEngine,
|
||||
ScreenInfo* screenInfo,
|
||||
QObject* app)
|
||||
{
|
||||
// setup the adapters (their lifetimes are that of MainApplication)
|
||||
auto avatarRegistry = new AvatarRegistry(lrcInstance, engine);
|
||||
auto callAdapter = new CallAdapter(settingsManager, systemTray, lrcInstance, engine);
|
||||
auto previewEngine = new PreviewEngine(connectivityMonitor, engine);
|
||||
auto imageDownloader = new ImageDownloader(connectivityMonitor, engine);
|
||||
auto messagesAdapter = new MessagesAdapter(settingsManager, previewEngine, lrcInstance, engine);
|
||||
auto positionManager = new PositionManager(settingsManager, systemTray, lrcInstance, engine);
|
||||
auto conversationsAdapter = new ConversationsAdapter(systemTray, lrcInstance, engine);
|
||||
auto avAdapter = new AvAdapter(lrcInstance, engine);
|
||||
auto contactAdapter = new ContactAdapter(lrcInstance, engine);
|
||||
auto accountAdapter = new AccountAdapter(settingsManager, systemTray, lrcInstance, engine);
|
||||
auto utilsAdapter = new UtilsAdapter(settingsManager, systemTray, lrcInstance, engine);
|
||||
auto pluginAdapter = new PluginAdapter(lrcInstance, settingsManager, engine);
|
||||
auto currentCall = new CurrentCall(lrcInstance, engine);
|
||||
auto currentConversation = new CurrentConversation(lrcInstance, engine);
|
||||
auto currentAccount = new CurrentAccount(lrcInstance, settingsManager, engine);
|
||||
auto tipsModel = new TipsModel(settingsManager, engine);
|
||||
auto videoDevices = new VideoDevices(lrcInstance, engine);
|
||||
auto currentAccountToMigrate = new CurrentAccountToMigrate(lrcInstance, engine);
|
||||
auto wizardViewStepModel = new WizardViewStepModel(lrcInstance, accountAdapter, settingsManager, engine);
|
||||
/* Used in ContactAdapter */
|
||||
auto connectionInfoListModel = new ConnectionInfoListModel(lrcInstance, app);
|
||||
qApp->setProperty("ConnectionInfoListModel", QVariant::fromValue(connectionInfoListModel));
|
||||
QQmlEngine::setObjectOwnership(connectionInfoListModel, QQmlEngine::CppOwnership);
|
||||
REG_QML_SINGLETON<ConnectionInfoListModel>(REG_MODEL, "ConnectionInfoListModel", CREATE(connectionInfoListModel));
|
||||
|
||||
/* Used in AccountAdapter */
|
||||
auto accountListModel = new AccountListModel(lrcInstance, app);
|
||||
qApp->setProperty("AccountListModel", QVariant::fromValue(accountListModel));
|
||||
QQmlEngine::setObjectOwnership(accountListModel, QQmlEngine::CppOwnership);
|
||||
REG_QML_SINGLETON<AccountListModel>(REG_MODEL, "AccountListModel", CREATE(accountListModel));
|
||||
|
||||
auto deviceItemListModel = new DeviceItemListModel(lrcInstance, app);
|
||||
qApp->setProperty("DeviceItemListModel", QVariant::fromValue(deviceItemListModel));
|
||||
QQmlEngine::setObjectOwnership(deviceItemListModel, QQmlEngine::CppOwnership);
|
||||
REG_QML_SINGLETON<DeviceItemListModel>(REG_MODEL, "DeviceItemListModel", CREATE(deviceItemListModel));
|
||||
|
||||
auto moderatorListModel = new ModeratorListModel(lrcInstance, app);
|
||||
qApp->setProperty("ModeratorListModel", QVariant::fromValue(moderatorListModel));
|
||||
QQmlEngine::setObjectOwnership(moderatorListModel, QQmlEngine::CppOwnership);
|
||||
REG_QML_SINGLETON<ModeratorListModel>(REG_MODEL, "ModeratorListModel", CREATE(moderatorListModel));
|
||||
|
||||
/* Used in CallAdapter */
|
||||
auto pttListener = new PTTListener(settingsManager, app);
|
||||
qApp->setProperty("PTTListener", QVariant::fromValue(pttListener));
|
||||
QQmlEngine::setObjectOwnership(pttListener, QQmlEngine::CppOwnership);
|
||||
REG_QML_SINGLETON<PTTListener>(REG_MODEL, "PTTListener", CREATE(pttListener));
|
||||
|
||||
auto callOverlayModel = new CallOverlayModel(lrcInstance, pttListener, app);
|
||||
qApp->setProperty("CallOverlayModel", QVariant::fromValue(callOverlayModel));
|
||||
QQmlEngine::setObjectOwnership(callOverlayModel, QQmlEngine::CppOwnership);
|
||||
REG_QML_SINGLETON<CallOverlayModel>(REG_MODEL, "CallOverlayModel", CREATE(callOverlayModel));
|
||||
|
||||
/* Used in CurrentCall */
|
||||
auto callParticipantsModel = new CallParticipantsModel(lrcInstance, app);
|
||||
qApp->setProperty("CallParticipantsModel", QVariant::fromValue(callParticipantsModel));
|
||||
QQmlEngine::setObjectOwnership(callParticipantsModel, QQmlEngine::CppOwnership);
|
||||
REG_QML_SINGLETON<CallParticipantsModel>(REG_MODEL, "CallParticipantsModel", CREATE(callParticipantsModel));
|
||||
|
||||
/* Used in ConversationsAdapter */
|
||||
auto convListProxyModel = new ConversationListProxyModel(nullptr, app);
|
||||
qApp->setProperty("ConvListProxyModel", QVariant::fromValue(convListProxyModel));
|
||||
auto searchProxyListModel = new SelectableListProxyModel(nullptr, app);
|
||||
qApp->setProperty("ConvSearchListProxyModel", QVariant::fromValue(searchProxyListModel));
|
||||
|
||||
// This causes mutually exclusive selection between the two proxy models.
|
||||
new SelectableListProxyGroupModel({convListProxyModel, searchProxyListModel}, app);
|
||||
|
||||
/* Used in PluginManager */
|
||||
auto pluginListModel = new PluginListModel(lrcInstance, app);
|
||||
qApp->setProperty("PluginListModel", QVariant::fromValue(pluginListModel));
|
||||
QQmlEngine::setObjectOwnership(pluginListModel, QQmlEngine::CppOwnership);
|
||||
REG_QML_SINGLETON<PluginListModel>(REG_MODEL, "PluginListModel", CREATE(pluginListModel));
|
||||
|
||||
auto pluginStoreListModel = new PluginStoreListModel(lrcInstance, app);
|
||||
qApp->setProperty("PluginStoreListModel", QVariant::fromValue(pluginStoreListModel));
|
||||
QQmlEngine::setObjectOwnership(pluginStoreListModel, QQmlEngine::CppOwnership);
|
||||
REG_QML_SINGLETON<PluginStoreListModel>(REG_MODEL, "PluginStoreListModel", CREATE(pluginStoreListModel));
|
||||
|
||||
// Register app-level objects that are used by QML created objects.
|
||||
// These MUST be set prior to loading the initial QML file, in order to
|
||||
// be available to the QML adapter class factory creation methods.
|
||||
qApp->setProperty("LRCInstance", QVariant::fromValue(lrcInstance));
|
||||
qApp->setProperty("SystemTray", QVariant::fromValue(systemTray));
|
||||
qApp->setProperty("AppSettingsManager", QVariant::fromValue(settingsManager));
|
||||
qApp->setProperty("ConnectivityMonitor", QVariant::fromValue(connectivityMonitor));
|
||||
qApp->setProperty("PreviewEngine", QVariant::fromValue(previewEngine));
|
||||
|
||||
// qml adapter registration
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_HELPERS, avatarRegistry, "AvatarRegistry");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, callAdapter, "CallAdapter");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, tipsModel, "TipsModel");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, messagesAdapter, "MessagesAdapter");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, positionManager, "PositionManager");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, conversationsAdapter, "ConversationsAdapter");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, avAdapter, "AvAdapter");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, contactAdapter, "ContactAdapter");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, accountAdapter, "AccountAdapter");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, utilsAdapter, "UtilsAdapter");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, pluginAdapter, "PluginAdapter");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentCall, "CurrentCall");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentConversation, "CurrentConversation");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentConversation->uris(), "CurrentConversationMembers");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentAccount, "CurrentAccount");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, videoDevices, "VideoDevices");
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentAccountToMigrate, "CurrentAccountToMigrate")
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, wizardViewStepModel, "WizardViewStepModel")
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_HELPERS, imageDownloader, "ImageDownloader")
|
||||
QML_REGISTERSINGLETON_TYPE(NS_HELPERS, AvatarRegistry);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, AccountAdapter);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, CallAdapter);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, MessagesAdapter);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, ConversationsAdapter);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, ContactAdapter);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, UtilsAdapter);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, PositionManager);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, AvAdapter);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, PluginAdapter);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, CurrentAccount);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, CurrentConversation);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, CurrentCall);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, TipsModel);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, VideoDevices);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_ADAPTERS, CurrentAccountToMigrate);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_MODELS, WizardViewStepModel);
|
||||
QML_REGISTERSINGLETON_TYPE(NS_HELPERS, ImageDownloader);
|
||||
|
||||
// TODO: remove these
|
||||
QML_REGISTERSINGLETONTYPE_CUSTOM(NS_MODELS, AVModel, &lrcInstance->avModel())
|
||||
QML_REGISTERSINGLETONTYPE_CUSTOM(NS_MODELS, PluginModel, &lrcInstance->pluginModel())
|
||||
QML_REGISTERSINGLETONTYPE_CUSTOM(NS_HELPERS, AppVersionManager, lrcInstance->getAppVersionManager())
|
||||
|
||||
// Hack for QtCreator autocomplete (part 2)
|
||||
// https://bugreports.qt.io/browse/QTCREATORBUG-20569
|
||||
// Use a dummy object to register the import namespace.
|
||||
// This occurs when we register from within MainApplication
|
||||
QML_REGISTERNAMESPACE(NS_MODELS, dummy::staticMetaObject, "");
|
||||
QML_REGISTERNAMESPACE(NS_ADAPTERS, dummy::staticMetaObject, "");
|
||||
QML_REGISTERNAMESPACE(NS_CONSTANTS, dummy::staticMetaObject, "");
|
||||
QML_REGISTERNAMESPACE(NS_HELPERS, dummy::staticMetaObject, "");
|
||||
QML_REGISTERNAMESPACE(NS_ENUMS, dummy::staticMetaObject, "");
|
||||
QML_REGISTERSINGLETONTYPE_WITH_INSTANCE(NameDirectory); // C++ singleton
|
||||
|
||||
// QAbstractListModels
|
||||
QML_REGISTERTYPE(NS_MODELS, BannedListModel);
|
||||
|
@ -176,10 +222,7 @@ registerTypes(QQmlEngine* engine,
|
|||
QML_REGISTERTYPE(NS_MODELS, PreferenceItemListModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, PluginListPreferenceModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, FilesToSendListModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, SmartListModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, MessageListModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, CallInformationListModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, RendererInformationListModel);
|
||||
|
||||
// Roles & type enums for models
|
||||
QML_REGISTERNAMESPACE(NS_MODELS, AccountList::staticMetaObject, "AccountList");
|
||||
|
@ -201,10 +244,6 @@ registerTypes(QQmlEngine* engine,
|
|||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_CONSTANTS, lrcInstance, "LRCInstance")
|
||||
QML_REGISTERSINGLETONTYPE_POBJECT(NS_CONSTANTS, settingsManager, "AppSettingsManager")
|
||||
|
||||
// C++ singletons
|
||||
// TODO: remove this
|
||||
QML_REGISTERSINGLETONTYPE_WITH_INSTANCE(NameDirectory);
|
||||
|
||||
// Lrc namespaces, models, and singletons
|
||||
QML_REGISTERNAMESPACE(NS_MODELS, lrc::api::staticMetaObject, "Lrc");
|
||||
QML_REGISTERNAMESPACE(NS_MODELS, lrc::api::account::staticMetaObject, "Account");
|
||||
|
@ -239,13 +278,7 @@ registerTypes(QQmlEngine* engine,
|
|||
QML_REGISTERUNCREATABLE(NS_ENUMS, VideoFormatFpsModel)
|
||||
|
||||
engine->addImageProvider(QLatin1String("qrImage"), new QrImageProvider(lrcInstance));
|
||||
engine->addImageProvider(QLatin1String("avatarimage"),
|
||||
new AvatarImageProvider(lrcInstance));
|
||||
|
||||
engine->setObjectOwnership(&lrcInstance->avModel(), QQmlEngine::CppOwnership);
|
||||
engine->setObjectOwnership(&lrcInstance->pluginModel(), QQmlEngine::CppOwnership);
|
||||
engine->setObjectOwnership(lrcInstance->getAppVersionManager(), QQmlEngine::CppOwnership);
|
||||
engine->setObjectOwnership(&NameDirectory::instance(), QQmlEngine::CppOwnership);
|
||||
engine->addImageProvider(QLatin1String("avatarimage"), new AvatarImageProvider(lrcInstance));
|
||||
}
|
||||
// clang-format on
|
||||
} // namespace Utils
|
||||
|
|
|
@ -46,6 +46,9 @@ Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
|
|||
} // namespace dummy
|
||||
|
||||
// clang-format off
|
||||
#define QML_REGISTERSINGLETON_TYPE(NS, T) \
|
||||
qmlRegisterSingletonType<T>(NS, MODULE_VER_MAJ, MODULE_VER_MIN, #T, T::create);
|
||||
|
||||
#define QML_REGISTERSINGLETONTYPE_POBJECT(NS, I, N) \
|
||||
QQmlEngine::setObjectOwnership(I, QQmlEngine::CppOwnership); \
|
||||
{ using T = std::remove_reference<decltype(*I)>::type; \
|
||||
|
@ -67,6 +70,7 @@ void registerTypes(QQmlEngine* engine,
|
|||
SystemTray* systemTray,
|
||||
AppSettingsManager* appSettingsManager,
|
||||
ConnectivityMonitor* connectivityMonitor,
|
||||
PreviewEngine* previewEngine,
|
||||
ScreenInfo* screenInfo,
|
||||
QObject* app);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ SettingsPageBase {
|
|||
|
||||
property bool isSIP: CurrentAccount.type === Profile.Type.SIP
|
||||
property int itemWidth: 132
|
||||
property string key: PttListener.keyToString(PttListener.getCurrentKey())
|
||||
property string key: PTTListener.keyToString(PTTListener.getCurrentKey())
|
||||
title: JamiStrings.callSettingsTitle
|
||||
|
||||
function updateAndShowModeratorsSlot() {
|
||||
|
@ -437,7 +437,7 @@ SettingsPageBase {
|
|||
onClicked: {
|
||||
var dlg = viewCoordinator.presentDialog(appWindow, "commoncomponents/ChangePttKeyPopup.qml");
|
||||
dlg.choiceMade.connect(function (chosenKey) {
|
||||
keyLabel.text = PttListener.keyToString(chosenKey);
|
||||
keyLabel.text = PTTListener.keyToString(chosenKey);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,13 +14,16 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import net.jami.Adapters 1.1
|
||||
import net.jami.Constants 1.1
|
||||
import net.jami.Enums 1.1
|
||||
import net.jami.Models 1.1
|
||||
|
||||
import "../../commoncomponents"
|
||||
import "../js/logviewwindowcreation.js" as LogViewWindowCreation
|
||||
|
||||
|
@ -109,16 +112,14 @@ ListView {
|
|||
|
||||
model: ConnectionInfoListModel
|
||||
|
||||
Component.onCompleted: {
|
||||
ContactAdapter.updateConnectionInfo();
|
||||
}
|
||||
Component.onCompleted: ConnectionInfoListModel.update()
|
||||
|
||||
Timer {
|
||||
interval: 1000
|
||||
running: root.visible
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
ContactAdapter.updateConnectionInfo();
|
||||
ConnectionInfoListModel.update();
|
||||
listview.rota = listview.rota + 5;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "lrcinstance.h"
|
||||
#include "appsettingsmanager.h"
|
||||
#include "qtutils.h"
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QObject>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
#define TIPS_ROLES \
|
||||
X(TipId) \
|
||||
|
@ -44,8 +46,14 @@ Q_ENUM_NS(Role)
|
|||
class TipsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
public:
|
||||
static TipsModel* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new TipsModel(qApp->property("AppSettingsManager").value<AppSettingsManager*>());
|
||||
}
|
||||
|
||||
TipsModel(AppSettingsManager* sm, QObject* parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
|
@ -58,4 +66,4 @@ public Q_SLOTS:
|
|||
private:
|
||||
VectorMapStringString tips_;
|
||||
AppSettingsManager* settingsManager_;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -30,12 +30,15 @@
|
|||
|
||||
#include <QApplication>
|
||||
#include <QObject>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
#if __has_include(<gio/gio.h>)
|
||||
#include <gio/gio.h>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && __has_include(<winrt/Windows.Foundation.h>)
|
||||
#define _SILENCE_CLANG_COROUTINE_MESSAGE
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
|
||||
#define WATCHSYSTEMTHEME __has_include(<winrt/Windows.UI.ViewManagement.h>)
|
||||
|
@ -67,9 +70,18 @@ bool readAppsUseLightThemeRegistry(bool getValue);
|
|||
class UtilsAdapter final : public QmlAdapterBase
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
QML_PROPERTY(QStringList, logList)
|
||||
QML_RO_PROPERTY(bool, isRTL)
|
||||
public:
|
||||
static UtilsAdapter* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new UtilsAdapter(qApp->property("AppSettingsManager").value<AppSettingsManager*>(),
|
||||
qApp->property("SystemTray").value<SystemTray*>(),
|
||||
qApp->property("LRCInstance").value<LRCInstance*>());
|
||||
}
|
||||
|
||||
explicit UtilsAdapter(AppSettingsManager* settingsManager,
|
||||
SystemTray* systemTray,
|
||||
LRCInstance* instance,
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
|
||||
#include "videodevices.h"
|
||||
|
||||
// VideoInputDeviceModel
|
||||
#include "api/devicemodel.h"
|
||||
|
||||
VideoInputDeviceModel::VideoInputDeviceModel(LRCInstance* lrcInstance,
|
||||
VideoDevices* videoDeviceInstance)
|
||||
: QAbstractListModel(videoDeviceInstance)
|
||||
|
@ -124,7 +125,6 @@ VideoFormatResolutionModel::getCurrentIndex() const
|
|||
return resultList.size() > 0 ? resultList[0].row() : 0;
|
||||
}
|
||||
|
||||
// VideoFormatFpsModel
|
||||
VideoFormatFpsModel::VideoFormatFpsModel(LRCInstance* lrcInstance, VideoDevices* videoDeviceInstance)
|
||||
: QAbstractListModel(videoDeviceInstance)
|
||||
, lrcInstance_(lrcInstance)
|
||||
|
@ -177,7 +177,6 @@ VideoFormatFpsModel::getCurrentIndex() const
|
|||
return resultList.size() > 0 ? resultList[0].row() : 0;
|
||||
}
|
||||
|
||||
// VideoDevices
|
||||
VideoDevices::VideoDevices(LRCInstance* lrcInstance, QObject* parent)
|
||||
: QObject(parent)
|
||||
, lrcInstance_(lrcInstance)
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
#include "lrcinstance.h"
|
||||
#include "qtutils.h"
|
||||
|
||||
#include "api/devicemodel.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class VideoDevices;
|
||||
|
||||
|
@ -115,6 +115,8 @@ private:
|
|||
class VideoDevices : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
|
||||
QML_RO_PROPERTY(int, listSize)
|
||||
|
||||
QML_RO_PROPERTY(QString, defaultChannel)
|
||||
|
@ -130,6 +132,11 @@ class VideoDevices : public QObject
|
|||
QML_RO_PROPERTY(QVariant, sharingFpsSourceModel)
|
||||
|
||||
public:
|
||||
static VideoDevices* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new VideoDevices(qApp->property("LRCInstance").value<LRCInstance*>());
|
||||
}
|
||||
|
||||
explicit VideoDevices(LRCInstance* lrcInstance, QObject* parent = nullptr);
|
||||
~VideoDevices() = default;
|
||||
|
||||
|
|
|
@ -50,6 +50,31 @@ BaseView {
|
|||
}
|
||||
}
|
||||
|
||||
// Handle the end of the wizard account creation process.
|
||||
Connections {
|
||||
target: WizardViewStepModel
|
||||
function onCreateAccountRequested(creationOption) {
|
||||
switch (creationOption) {
|
||||
case WizardViewStepModel.AccountCreationOption.CreateJamiAccount:
|
||||
case WizardViewStepModel.AccountCreationOption.CreateRendezVous:
|
||||
case WizardViewStepModel.AccountCreationOption.ImportFromBackup:
|
||||
case WizardViewStepModel.AccountCreationOption.ImportFromDevice:
|
||||
AccountAdapter.createJamiAccount(WizardViewStepModel.accountCreationInfo);
|
||||
break;
|
||||
case WizardViewStepModel.AccountCreationOption.ConnectToAccountManager:
|
||||
AccountAdapter.createJAMSAccount(WizardViewStepModel.accountCreationInfo);
|
||||
break;
|
||||
case WizardViewStepModel.AccountCreationOption.CreateSipAccount:
|
||||
AccountAdapter.createSIPAccount(WizardViewStepModel.accountCreationInfo);
|
||||
break;
|
||||
default:
|
||||
print("Bad account creation option: " + creationOption);
|
||||
WizardViewStepModel.closeWizardView();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: WizardViewStepModel
|
||||
|
||||
|
|
|
@ -18,26 +18,23 @@
|
|||
|
||||
#include "wizardviewstepmodel.h"
|
||||
|
||||
#include "accountadapter.h"
|
||||
#include "appsettingsmanager.h"
|
||||
#include "lrcinstance.h"
|
||||
|
||||
#include "api/accountmodel.h"
|
||||
|
||||
WizardViewStepModel::WizardViewStepModel(LRCInstance* lrcInstance,
|
||||
AccountAdapter* accountAdapter,
|
||||
AppSettingsManager* appSettingsManager,
|
||||
QObject* parent)
|
||||
: QObject(parent)
|
||||
, lrcInstance_(lrcInstance)
|
||||
, accountAdapter_(accountAdapter)
|
||||
, appSettingsManager_(appSettingsManager)
|
||||
{
|
||||
reset();
|
||||
|
||||
connect(accountAdapter_,
|
||||
&AccountAdapter::accountAdded,
|
||||
connect(&lrcInstance_->accountModel(),
|
||||
&AccountModel::accountAdded,
|
||||
this,
|
||||
[this](QString accountId, int index) {
|
||||
accountAdapter_->changeAccount(index);
|
||||
|
||||
[this](const QString& accountId) {
|
||||
auto accountCreationOption = get_accountCreationOption();
|
||||
if (accountCreationOption == AccountCreationOption::ConnectToAccountManager
|
||||
|| accountCreationOption == AccountCreationOption::CreateSipAccount) {
|
||||
|
@ -66,30 +63,8 @@ WizardViewStepModel::startAccountCreationFlow(AccountCreationOption accountCreat
|
|||
void
|
||||
WizardViewStepModel::nextStep()
|
||||
{
|
||||
auto accountCreationOption = get_accountCreationOption();
|
||||
if (get_mainStep() == MainSteps::Initial
|
||||
|| accountCreationOption == AccountCreationOption::None) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (accountCreationOption) {
|
||||
case AccountCreationOption::CreateJamiAccount:
|
||||
case AccountCreationOption::CreateRendezVous:
|
||||
case AccountCreationOption::ImportFromBackup:
|
||||
case AccountCreationOption::ImportFromDevice: {
|
||||
accountAdapter_->createJamiAccount(get_accountCreationInfo());
|
||||
break;
|
||||
}
|
||||
case AccountCreationOption::ConnectToAccountManager: {
|
||||
accountAdapter_->createJAMSAccount(get_accountCreationInfo());
|
||||
break;
|
||||
}
|
||||
case AccountCreationOption::CreateSipAccount: {
|
||||
accountAdapter_->createSIPAccount(get_accountCreationInfo());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
if (mainStep_ != MainSteps::Initial) {
|
||||
Q_EMIT createAccountRequested(accountCreationOption_);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,11 +18,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "qtutils.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QMap>
|
||||
|
||||
#include "qtutils.h"
|
||||
#include <QQmlEngine> // QML registration
|
||||
#include <QApplication> // QML registration
|
||||
|
||||
class AccountAdapter;
|
||||
class LRCInstance;
|
||||
|
@ -31,6 +33,7 @@ class AppSettingsManager;
|
|||
class WizardViewStepModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_SINGLETON
|
||||
Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
|
||||
|
||||
public:
|
||||
|
@ -54,12 +57,17 @@ public:
|
|||
|
||||
QML_PROPERTY(MainSteps, mainStep)
|
||||
QML_PROPERTY(AccountCreationOption, accountCreationOption)
|
||||
|
||||
QML_PROPERTY(QVariantMap, accountCreationInfo)
|
||||
|
||||
public:
|
||||
static WizardViewStepModel* create(QQmlEngine*, QJSEngine*)
|
||||
{
|
||||
return new WizardViewStepModel(qApp->property("LRCInstance").value<LRCInstance*>(),
|
||||
qApp->property("AppSettingsManager")
|
||||
.value<AppSettingsManager*>());
|
||||
}
|
||||
|
||||
explicit WizardViewStepModel(LRCInstance* lrcInstance,
|
||||
AccountAdapter* accountAdapter,
|
||||
AppSettingsManager* appSettingsManager,
|
||||
QObject* parent = nullptr);
|
||||
|
||||
|
@ -70,11 +78,11 @@ public:
|
|||
Q_SIGNALS:
|
||||
void accountIsReady(QString accountId);
|
||||
void closeWizardView();
|
||||
void createAccountRequested(AccountCreationOption);
|
||||
|
||||
private:
|
||||
void reset();
|
||||
|
||||
LRCInstance* lrcInstance_;
|
||||
AccountAdapter* accountAdapter_;
|
||||
AppSettingsManager* appSettingsManager_;
|
||||
};
|
||||
|
|
|
@ -136,6 +136,7 @@ public Q_SLOTS:
|
|||
systemTray_.get(),
|
||||
settingsManager_.get(),
|
||||
connectivityMonitor_.get(),
|
||||
previewEngine_.get(),
|
||||
&screenInfo_,
|
||||
this);
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtTest
|
||||
|
||||
import "../../../src/app/"
|
||||
|
||||
|
@ -24,8 +25,18 @@ import "../../../src/app/"
|
|||
// each UUT from having to manage its own top level app management objects
|
||||
// (currently ViewManager, ViewCoordinator, and ApplicationWindow).
|
||||
Item {
|
||||
// This will be our UUT.
|
||||
required default property var uut
|
||||
id: tw
|
||||
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
|
||||
// A binding to the windowShown property
|
||||
Binding {
|
||||
tw.appWindow: uut.Window.window
|
||||
when: QTestRootObject.windowShown
|
||||
}
|
||||
|
||||
Component.onCompleted: viewCoordinator.init(this)
|
||||
|
||||
// These are our fake app management objects. The caveat is that they
|
||||
// must be maintained in sync with the actual objects in the app for now.
|
||||
|
@ -33,7 +44,7 @@ Item {
|
|||
// sync them.
|
||||
property ViewManager viewManager: ViewManager {}
|
||||
property ViewCoordinator viewCoordinator: ViewCoordinator {}
|
||||
property ApplicationWindow appWindow: ApplicationWindow {
|
||||
property QtObject appWindow: QtObject {
|
||||
property bool useFrameless: false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,17 +28,20 @@ import "../../../src/app/mainview"
|
|||
import "../../../src/app/mainview/components"
|
||||
import "../../../src/app/commoncomponents"
|
||||
|
||||
CallMessageDelegate {
|
||||
id: uut
|
||||
type: Interaction.Type.CALL
|
||||
TestWrapper {
|
||||
CallMessageDelegate {
|
||||
id: uut
|
||||
|
||||
TestCase {
|
||||
name: "Check basic visibility for header buttons"
|
||||
function test_checkBasicVisibility() {
|
||||
var moreButton = findChild(uut, "more")
|
||||
var replyButton = findChild(uut, "reply")
|
||||
compare(moreButton.visible, false)
|
||||
compare(replyButton.visible, false)
|
||||
type: Interaction.Type.CALL
|
||||
|
||||
TestCase {
|
||||
name: "Check basic visibility for option buttons"
|
||||
function test_checkOptionButtonsVisibility() {
|
||||
var moreButton = findChild(uut, "more")
|
||||
var replyButton = findChild(uut, "reply")
|
||||
compare(moreButton.visible, false)
|
||||
compare(replyButton.visible, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,67 +25,59 @@ import net.jami.Constants 1.1
|
|||
import "../../../src/app/"
|
||||
import "../../../src/app/mainview/components"
|
||||
|
||||
OngoingCallPage {
|
||||
id: uut
|
||||
TestWrapper {
|
||||
OngoingCallPage {
|
||||
id: uut
|
||||
|
||||
width: 800
|
||||
height: 600
|
||||
width: 800
|
||||
height: 600
|
||||
|
||||
property QtObject appWindow
|
||||
property ViewManager viewManager: ViewManager {}
|
||||
property ViewCoordinator viewCoordinator: ViewCoordinator {}
|
||||
TestCase {
|
||||
name: "Check basic visibility of action bar during a call"
|
||||
when: windowShown // Mouse events can only be handled
|
||||
// after the window has been shown.
|
||||
|
||||
TestCase {
|
||||
name: "Check basic visibility of action bar during a call"
|
||||
when: windowShown // Mouse events can only be handled
|
||||
// after the window has been shown.
|
||||
property var mainOverlay
|
||||
|
||||
property var callOverlay
|
||||
property var mainOverlay
|
||||
function initTestCase() {
|
||||
mainOverlay = findChild(uut, "mainOverlay")
|
||||
|
||||
function initTestCase() {
|
||||
callOverlay = findChild(uut, "callOverlay")
|
||||
mainOverlay = findChild(callOverlay, "mainOverlay")
|
||||
// The CallActionBar on the OngoingCallPage starts out invisible and
|
||||
// is made visible whenever the user moves their mouse.
|
||||
// This is implemented via an event filter in the CallOverlayModel
|
||||
// class. The event filter is created when the MainOverlay becomes
|
||||
// visible. In the actual Jami application, this happens when a call
|
||||
// is started, but we need to toggle the visiblity manually here
|
||||
// because the MainOverlay is visible at the beginning of the test.
|
||||
mainOverlay.visible = false
|
||||
mainOverlay.visible = true
|
||||
}
|
||||
|
||||
// The CallActionBar on the OngoingCallPage starts out invisible and
|
||||
// is made visible whenever the user moves their mouse.
|
||||
// This is implemented via an event filter in the CallOverlayModel
|
||||
// class. The event filter is created when the MainOverlay becomes
|
||||
// visible. In the actual Jami application, this happens when a call
|
||||
// is started, but we need to toggle the visiblity manually here
|
||||
// because the MainOverlay is visible at the beginning of the test.
|
||||
appWindow = uut.Window.window
|
||||
mainOverlay.visible = false
|
||||
mainOverlay.visible = true
|
||||
function test_checkCallActionBarVisibility() {
|
||||
var callActionBar = findChild(mainOverlay, "callActionBar")
|
||||
|
||||
// Calling mouseMove() will generate warnings if we don't call init first.
|
||||
viewCoordinator.init(uut)
|
||||
}
|
||||
// The primary and secondary actions in the CallActionBar are currently being added
|
||||
// one by one (not using a loop) to CallOverlayModel in the Component.onCompleted
|
||||
// block of CallActionBar.qml. The two lines below are meant as a sanity check
|
||||
// that no action has been forgotten.
|
||||
compare(callActionBar.primaryActions.length, CallOverlayModel.primaryModel().rowCount())
|
||||
compare(callActionBar.secondaryActions.length, CallOverlayModel.secondaryModel().rowCount())
|
||||
|
||||
function test_checkBasicVisibility() {
|
||||
var callActionBar = findChild(mainOverlay, "callActionBar")
|
||||
compare(callActionBar.visible, false)
|
||||
mouseMove(uut)
|
||||
|
||||
// The primary and secondary actions in the CallActionBar are currently being added
|
||||
// one by one (not using a loop) to CallOverlayModel in the Component.onCompleted
|
||||
// block of CallActionBar.qml. The two lines below are meant as a sanity check
|
||||
// that no action has been forgotten.
|
||||
compare(callActionBar.primaryActions.length, CallOverlayModel.primaryModel().rowCount())
|
||||
compare(callActionBar.secondaryActions.length, CallOverlayModel.secondaryModel().rowCount())
|
||||
// We need to wait for the fade-in animation of the CallActionBar to be completed
|
||||
// before we check that it's visible.
|
||||
var waitTime = JamiTheme.overlayFadeDuration + 100
|
||||
// Make sure we have time to check that the CallActioinBar is visible before it fades out:
|
||||
verify(waitTime + 100 < JamiTheme.overlayFadeDelay)
|
||||
// Note: The CallActionBar is supposed to stay visible for a few seconds. If the above
|
||||
// check fails, then this means that either overlayFadeDuration or overlayFadeDelay
|
||||
// got changed to a value that's way too high/low.
|
||||
|
||||
compare(callActionBar.visible, false)
|
||||
mouseMove(uut)
|
||||
|
||||
// We need to wait for the fade-in animation of the CallActionBar to be completed
|
||||
// before we check that it's visible.
|
||||
var waitTime = JamiTheme.overlayFadeDuration + 100
|
||||
// Make sure we have time to check that the CallActioinBar is visible before it fades out:
|
||||
verify(waitTime + 100 < JamiTheme.overlayFadeDelay)
|
||||
// Note: The CallActionBar is supposed to stay visible for a few seconds. If the above
|
||||
// check fails, then this means that either overlayFadeDuration or overlayFadeDelay
|
||||
// got changed to a value that's way too high/low.
|
||||
|
||||
wait(waitTime)
|
||||
compare(callActionBar.visible, true)
|
||||
wait(waitTime)
|
||||
compare(callActionBar.visible, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,9 +24,12 @@ import "../../../src/app/"
|
|||
import "../../../src/app/mainview/components"
|
||||
|
||||
TestWrapper {
|
||||
uut: WelcomePage {
|
||||
WelcomePage {
|
||||
id: uut
|
||||
|
||||
TestCase {
|
||||
name: "Open 'About Jami' popup"
|
||||
when: windowShown
|
||||
|
||||
function test_openAboutPopup() {
|
||||
var aboutJamiButton = findChild(uut, "aboutJami")
|
||||
|
|
Loading…
Reference in a new issue