Send message, composing notification
This commit is contained in:
parent
bdff2bddcd
commit
ecd9373df9
17 changed files with 363 additions and 124 deletions
|
|
@ -162,6 +162,37 @@ void ChatCore::setSelf(QSharedPointer<ChatCore> me) {
|
||||||
mChatModelConnection->invokeToCore([this, message]() { setLastMessageInHistory(message); });
|
mChatModelConnection->invokeToCore([this, message]() { setLastMessageInHistory(message); });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
mChatModelConnection->makeConnectToCore(&ChatCore::lSendTextMessage, [this](QString message) {
|
||||||
|
mChatModelConnection->invokeToModel([this, message]() {
|
||||||
|
auto linMessage = mChatModel->createTextMessageFromText(message);
|
||||||
|
linMessage->send();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
mChatModelConnection->makeConnectToModel(
|
||||||
|
&ChatModel::chatMessageSending, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
const std::shared_ptr<const linphone::EventLog> &eventLog) {
|
||||||
|
auto message = eventLog->getChatMessage();
|
||||||
|
if (message) {
|
||||||
|
auto newMessage = ChatMessageCore::create(message);
|
||||||
|
mChatModelConnection->invokeToCore([this, newMessage]() { appendMessageToMessageList(newMessage); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mChatModelConnection->makeConnectToCore(
|
||||||
|
&ChatCore::lCompose, [this]() { mChatModelConnection->invokeToModel([this]() { mChatModel->compose(); }); });
|
||||||
|
mChatModelConnection->makeConnectToModel(
|
||||||
|
&ChatModel::isComposingReceived,
|
||||||
|
[this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
const std::shared_ptr<const linphone::Address> &remoteAddress, bool isComposing) {
|
||||||
|
if (mChatModel->getMonitor() != chatRoom) return;
|
||||||
|
QString name = isComposing ? ToolModel::getDisplayName(remoteAddress->clone()) : QString();
|
||||||
|
auto remoteAddr = remoteAddress->clone();
|
||||||
|
remoteAddr->clean();
|
||||||
|
mChatModelConnection->invokeToCore(
|
||||||
|
[this, name, address = Utils::coreStringToAppString(remoteAddr->asStringUriOnly())]() {
|
||||||
|
setComposingName(name);
|
||||||
|
setComposingAddress(address);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime ChatCore::getLastUpdatedTime() const {
|
QDateTime ChatCore::getLastUpdatedTime() const {
|
||||||
|
|
@ -275,6 +306,28 @@ void ChatCore::clearMessagesList() {
|
||||||
emit messageListChanged();
|
emit messageListChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ChatCore::getComposingName() const {
|
||||||
|
return mComposingName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatCore::setComposingName(QString composingName) {
|
||||||
|
if (mComposingAddress != composingName) {
|
||||||
|
mComposingName = composingName;
|
||||||
|
emit composingUserChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatCore::setComposingAddress(QString composingAddress) {
|
||||||
|
if (mComposingAddress != composingAddress) {
|
||||||
|
mComposingAddress = composingAddress;
|
||||||
|
emit composingUserChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ChatCore::getComposingAddress() const {
|
||||||
|
return mComposingAddress;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<ChatModel> ChatCore::getModel() const {
|
std::shared_ptr<ChatModel> ChatCore::getModel() const {
|
||||||
return mChatModel;
|
return mChatModel;
|
||||||
}
|
}
|
||||||
|
|
@ -43,6 +43,8 @@ public:
|
||||||
lastMessageInHistoryChanged)
|
lastMessageInHistoryChanged)
|
||||||
Q_PROPERTY(int unreadMessagesCount READ getUnreadMessagesCount WRITE setUnreadMessagesCount NOTIFY
|
Q_PROPERTY(int unreadMessagesCount READ getUnreadMessagesCount WRITE setUnreadMessagesCount NOTIFY
|
||||||
unreadMessagesCountChanged)
|
unreadMessagesCountChanged)
|
||||||
|
Q_PROPERTY(QString composingName READ getComposingName WRITE setComposingName NOTIFY composingUserChanged)
|
||||||
|
Q_PROPERTY(QString composingAddress READ getComposingAddress WRITE setComposingAddress NOTIFY composingUserChanged)
|
||||||
// Q_PROPERTY(VideoStats videoStats READ getVideoStats WRITE setVideoStats NOTIFY videoStatsChanged)
|
// Q_PROPERTY(VideoStats videoStats READ getVideoStats WRITE setVideoStats NOTIFY videoStatsChanged)
|
||||||
|
|
||||||
// Should be call from model Thread. Will be automatically in App thread after initialization
|
// Should be call from model Thread. Will be automatically in App thread after initialization
|
||||||
|
|
@ -78,6 +80,11 @@ public:
|
||||||
QString getAvatarUri() const;
|
QString getAvatarUri() const;
|
||||||
void setAvatarUri(QString avatarUri);
|
void setAvatarUri(QString avatarUri);
|
||||||
|
|
||||||
|
QString getComposingName() const;
|
||||||
|
QString getComposingAddress() const;
|
||||||
|
void setComposingName(QString composingName);
|
||||||
|
void setComposingAddress(QString composingAddress);
|
||||||
|
|
||||||
std::shared_ptr<ChatModel> getModel() const;
|
std::shared_ptr<ChatModel> getModel() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
@ -89,6 +96,7 @@ signals:
|
||||||
void messageListChanged();
|
void messageListChanged();
|
||||||
void avatarUriChanged();
|
void avatarUriChanged();
|
||||||
void deleted();
|
void deleted();
|
||||||
|
void composingUserChanged();
|
||||||
|
|
||||||
void lDeleteMessage();
|
void lDeleteMessage();
|
||||||
void lDelete();
|
void lDelete();
|
||||||
|
|
@ -96,6 +104,8 @@ signals:
|
||||||
void lMarkAsRead();
|
void lMarkAsRead();
|
||||||
void lUpdateLastMessage();
|
void lUpdateLastMessage();
|
||||||
void lUpdateUnreadCount();
|
void lUpdateUnreadCount();
|
||||||
|
void lSendTextMessage(QString message);
|
||||||
|
void lCompose();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString id;
|
QString id;
|
||||||
|
|
@ -106,6 +116,8 @@ private:
|
||||||
QString mIdentifier;
|
QString mIdentifier;
|
||||||
QString mAvatarUri;
|
QString mAvatarUri;
|
||||||
int mUnreadMessagesCount;
|
int mUnreadMessagesCount;
|
||||||
|
QString mComposingName;
|
||||||
|
QString mComposingAddress;
|
||||||
std::shared_ptr<ChatModel> mChatModel;
|
std::shared_ptr<ChatModel> mChatModel;
|
||||||
QList<QSharedPointer<ChatMessageCore>> mChatMessageList;
|
QList<QSharedPointer<ChatMessageCore>> mChatMessageList;
|
||||||
QSharedPointer<SafeConnection<ChatCore, ChatModel>> mChatModelConnection;
|
QSharedPointer<SafeConnection<ChatCore, ChatModel>> mChatModelConnection;
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,14 @@ ChatMessageCore::ChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &c
|
||||||
mIsRemoteMessage = !from->weakEqual(to);
|
mIsRemoteMessage = !from->weakEqual(to);
|
||||||
mPeerAddress = Utils::coreStringToAppString(chatmessage->getPeerAddress()->asStringUriOnly());
|
mPeerAddress = Utils::coreStringToAppString(chatmessage->getPeerAddress()->asStringUriOnly());
|
||||||
mPeerName = ToolModel::getDisplayName(chatmessage->getPeerAddress()->clone());
|
mPeerName = ToolModel::getDisplayName(chatmessage->getPeerAddress()->clone());
|
||||||
|
auto fromAddress = chatmessage->getFromAddress()->clone();
|
||||||
|
fromAddress->clean();
|
||||||
|
mFromAddress = Utils::coreStringToAppString(fromAddress->asStringUriOnly());
|
||||||
|
mFromName = ToolModel::getDisplayName(chatmessage->getFromAddress()->clone());
|
||||||
|
|
||||||
|
auto chatroom = chatmessage->getChatRoom();
|
||||||
|
mIsFromChatGroup = chatroom->hasCapability((int)linphone::ChatRoom::Capabilities::Conference) &&
|
||||||
|
!chatroom->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatMessageCore::~ChatMessageCore() {
|
ChatMessageCore::~ChatMessageCore() {
|
||||||
|
|
@ -91,15 +99,24 @@ QString ChatMessageCore::getPeerName() const {
|
||||||
return mPeerName;
|
return mPeerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ChatMessageCore::getFromAddress() const {
|
||||||
|
return mFromAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ChatMessageCore::getFromName() const {
|
||||||
|
return mFromName;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ChatMessageCore::getToAddress() const {
|
||||||
|
return mToAddress;
|
||||||
|
}
|
||||||
|
|
||||||
bool ChatMessageCore::isRemoteMessage() const {
|
bool ChatMessageCore::isRemoteMessage() const {
|
||||||
return mIsRemoteMessage;
|
return mIsRemoteMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatMessageCore::setIsRemoteMessage(bool isRemote) {
|
bool ChatMessageCore::isFromChatGroup() const {
|
||||||
if (mIsRemoteMessage != isRemote) {
|
return mIsFromChatGroup;
|
||||||
mIsRemoteMessage = isRemote;
|
|
||||||
emit isRemoteMessageChanged(isRemote);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ChatMessageModel> ChatMessageCore::getModel() const {
|
std::shared_ptr<ChatMessageModel> ChatMessageCore::getModel() const {
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,12 @@ class ChatMessageCore : public QObject, public AbstractObject {
|
||||||
Q_PROPERTY(QDateTime timestamp READ getTimestamp WRITE setTimestamp NOTIFY timestampChanged)
|
Q_PROPERTY(QDateTime timestamp READ getTimestamp WRITE setTimestamp NOTIFY timestampChanged)
|
||||||
Q_PROPERTY(QString text READ getText WRITE setText NOTIFY textChanged)
|
Q_PROPERTY(QString text READ getText WRITE setText NOTIFY textChanged)
|
||||||
Q_PROPERTY(QString peerAddress READ getPeerAddress CONSTANT)
|
Q_PROPERTY(QString peerAddress READ getPeerAddress CONSTANT)
|
||||||
|
Q_PROPERTY(QString fromAddress READ getFromAddress CONSTANT)
|
||||||
|
Q_PROPERTY(QString toAddress READ getToAddress CONSTANT)
|
||||||
Q_PROPERTY(QString peerName READ getPeerName CONSTANT)
|
Q_PROPERTY(QString peerName READ getPeerName CONSTANT)
|
||||||
Q_PROPERTY(bool isRemoteMessage READ isRemoteMessage WRITE setIsRemoteMessage NOTIFY isRemoteMessageChanged)
|
Q_PROPERTY(QString fromName READ getFromName CONSTANT)
|
||||||
|
Q_PROPERTY(bool isRemoteMessage READ isRemoteMessage CONSTANT)
|
||||||
|
Q_PROPERTY(bool isFromChatGroup READ isFromChatGroup CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static QSharedPointer<ChatMessageCore> create(const std::shared_ptr<linphone::ChatMessage> &chatmessage);
|
static QSharedPointer<ChatMessageCore> create(const std::shared_ptr<linphone::ChatMessage> &chatmessage);
|
||||||
|
|
@ -53,9 +57,12 @@ public:
|
||||||
|
|
||||||
QString getPeerAddress() const;
|
QString getPeerAddress() const;
|
||||||
QString getPeerName() const;
|
QString getPeerName() const;
|
||||||
|
QString getFromAddress() const;
|
||||||
|
QString getFromName() const;
|
||||||
|
QString getToAddress() const;
|
||||||
|
|
||||||
bool isRemoteMessage() const;
|
bool isRemoteMessage() const;
|
||||||
void setIsRemoteMessage(bool isRemote);
|
bool isFromChatGroup() const;
|
||||||
|
|
||||||
std::shared_ptr<ChatMessageModel> getModel() const;
|
std::shared_ptr<ChatMessageModel> getModel() const;
|
||||||
|
|
||||||
|
|
@ -70,9 +77,13 @@ signals:
|
||||||
private:
|
private:
|
||||||
DECLARE_ABSTRACT_OBJECT QString mText;
|
DECLARE_ABSTRACT_OBJECT QString mText;
|
||||||
QString mPeerAddress;
|
QString mPeerAddress;
|
||||||
|
QString mFromAddress;
|
||||||
|
QString mToAddress;
|
||||||
|
QString mFromName;
|
||||||
QString mPeerName;
|
QString mPeerName;
|
||||||
QDateTime mTimestamp;
|
QDateTime mTimestamp;
|
||||||
bool mIsRemoteMessage = false;
|
bool mIsRemoteMessage = false;
|
||||||
|
bool mIsFromChatGroup = false;
|
||||||
std::shared_ptr<ChatMessageModel> mChatMessageModel;
|
std::shared_ptr<ChatMessageModel> mChatMessageModel;
|
||||||
QSharedPointer<SafeConnection<ChatMessageCore, ChatMessageModel>> mChatMessageModelConnection;
|
QSharedPointer<SafeConnection<ChatMessageCore, ChatMessageModel>> mChatMessageModelConnection;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -46,19 +46,30 @@ void ChatMessageProxy::setSourceModel(QAbstractItemModel *model) {
|
||||||
sort(0);
|
sort(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatGui* ChatMessageProxy::getChatGui() {
|
ChatGui *ChatMessageProxy::getChatGui() {
|
||||||
auto model = getListModel<ChatMessageList>();
|
auto model = getListModel<ChatMessageList>();
|
||||||
if (!mChatGui && model) mChatGui = model->getChat();
|
if (!mChatGui && model) mChatGui = model->getChat();
|
||||||
return mChatGui;
|
return mChatGui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatMessageProxy::setChatGui(ChatGui* chat) {
|
void ChatMessageProxy::setChatGui(ChatGui *chat) {
|
||||||
getListModel<ChatMessageList>()->setChatGui(chat);
|
getListModel<ChatMessageList>()->setChatGui(chat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChatMessageGui *ChatMessageProxy::getChatMessageAtIndex(int i) {
|
||||||
|
auto model = getListModel<ChatMessageList>();
|
||||||
|
auto sourceIndex = mapToSource(index(i, 0)).row();
|
||||||
|
if (model) {
|
||||||
|
auto chat = model->getAt<ChatMessageCore>(sourceIndex);
|
||||||
|
if (chat) return new ChatMessageGui(chat);
|
||||||
|
else return nullptr;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool ChatMessageProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
bool ChatMessageProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
||||||
// auto l = getItemAtSource<ChatMessageList, ChatMessageCore>(sourceRow);
|
// auto l = getItemAtSource<ChatMessageList, ChatMessageCore>(sourceRow);
|
||||||
// return l != nullptr;
|
// return l != nullptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@
|
||||||
#ifndef CHAT_MESSAGE_PROXY_H_
|
#ifndef CHAT_MESSAGE_PROXY_H_
|
||||||
#define CHAT_MESSAGE_PROXY_H_
|
#define CHAT_MESSAGE_PROXY_H_
|
||||||
|
|
||||||
#include "core/proxy/LimitProxy.hpp"
|
|
||||||
#include "ChatMessageList.hpp"
|
#include "ChatMessageList.hpp"
|
||||||
|
#include "core/proxy/LimitProxy.hpp"
|
||||||
#include "tool/AbstractObject.hpp"
|
#include "tool/AbstractObject.hpp"
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
@ -31,7 +31,7 @@ class ChatGui;
|
||||||
|
|
||||||
class ChatMessageProxy : public LimitProxy, public AbstractObject {
|
class ChatMessageProxy : public LimitProxy, public AbstractObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(ChatGui* chatGui READ getChatGui WRITE setChatGui NOTIFY chatChanged)
|
Q_PROPERTY(ChatGui *chatGui READ getChatGui WRITE setChatGui NOTIFY chatChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DECLARE_SORTFILTER_CLASS()
|
DECLARE_SORTFILTER_CLASS()
|
||||||
|
|
@ -39,17 +39,19 @@ public:
|
||||||
ChatMessageProxy(QObject *parent = Q_NULLPTR);
|
ChatMessageProxy(QObject *parent = Q_NULLPTR);
|
||||||
~ChatMessageProxy();
|
~ChatMessageProxy();
|
||||||
|
|
||||||
ChatGui* getChatGui();
|
ChatGui *getChatGui();
|
||||||
void setChatGui(ChatGui* chat);
|
void setChatGui(ChatGui *chat);
|
||||||
|
|
||||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||||
|
|
||||||
|
Q_INVOKABLE ChatMessageGui *getChatMessageAtIndex(int index);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void chatChanged();
|
void chatChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QSharedPointer<ChatMessageList> mList;
|
QSharedPointer<ChatMessageList> mList;
|
||||||
ChatGui* mChatGui = nullptr;
|
ChatGui *mChatGui = nullptr;
|
||||||
DECLARE_ABSTRACT_OBJECT
|
DECLARE_ABSTRACT_OBJECT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,14 @@ void ChatModel::deleteChatRoom() {
|
||||||
emit deleted();
|
emit deleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<linphone::ChatMessage> ChatModel::createTextMessageFromText(QString text) {
|
||||||
|
return mMonitor->createMessageFromUtf8(Utils::appStringToCoreString(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatModel::compose() {
|
||||||
|
mMonitor->compose();
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------//
|
//---------------------------------------------------------------//
|
||||||
|
|
||||||
void ChatModel::onIsComposingReceived(const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
void ChatModel::onIsComposingReceived(const std::shared_ptr<linphone::ChatRoom> &chatRoom,
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ public:
|
||||||
QString getIdentifier() const;
|
QString getIdentifier() const;
|
||||||
void deleteHistory();
|
void deleteHistory();
|
||||||
void deleteChatRoom();
|
void deleteChatRoom();
|
||||||
|
std::shared_ptr<linphone::ChatMessage> createTextMessageFromText(QString text);
|
||||||
|
void compose();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void historyDeleted();
|
void historyDeleted();
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,14 @@ QString ChatMessageModel::getPeerAddress() const {
|
||||||
return Utils::coreStringToAppString(mMonitor->getPeerAddress()->asStringUriOnly());
|
return Utils::coreStringToAppString(mMonitor->getPeerAddress()->asStringUriOnly());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ChatMessageModel::getFromAddress() const {
|
||||||
|
return Utils::coreStringToAppString(mMonitor->getFromAddress()->asStringUriOnly());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ChatMessageModel::getToAddress() const {
|
||||||
|
return Utils::coreStringToAppString(mMonitor->getToAddress()->asStringUriOnly());
|
||||||
|
}
|
||||||
|
|
||||||
QDateTime ChatMessageModel::getTimestamp() const {
|
QDateTime ChatMessageModel::getTimestamp() const {
|
||||||
return QDateTime::fromSecsSinceEpoch(mMonitor->getTime());
|
return QDateTime::fromSecsSinceEpoch(mMonitor->getTime());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ public:
|
||||||
QDateTime getTimestamp() const;
|
QDateTime getTimestamp() const;
|
||||||
|
|
||||||
QString getPeerAddress() const;
|
QString getPeerAddress() const;
|
||||||
|
QString getFromAddress() const;
|
||||||
|
QString getToAddress() const;
|
||||||
|
|
||||||
void deleteMessageFromChatRoom();
|
void deleteMessageFromChatRoom();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,115 +8,136 @@ import SettingsCpp
|
||||||
import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle
|
import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle
|
||||||
import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils
|
import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils
|
||||||
|
|
||||||
Control.Control {
|
|
||||||
|
RowLayout {
|
||||||
id: mainItem
|
id: mainItem
|
||||||
property color backgroundColor
|
property color backgroundColor
|
||||||
property bool isRemoteMessage
|
|
||||||
property bool isFirstMessage
|
property bool isFirstMessage
|
||||||
|
|
||||||
property string imgUrl
|
property string imgUrl
|
||||||
property string contentText
|
spacing: 0
|
||||||
|
|
||||||
|
property ChatMessageGui chatMessage
|
||||||
|
property string fromAddress: chatMessage? chatMessage.core.fromAddress : ""
|
||||||
|
property bool isRemoteMessage: chatMessage? chatMessage.core.isRemoteMessage : false
|
||||||
|
property bool isFromChatGroup: chatMessage? chatMessage.core.isFromChatGroup : false
|
||||||
|
|
||||||
topPadding: Math.round(12 * DefaultStyle.dp)
|
|
||||||
bottomPadding: Math.round(12 * DefaultStyle.dp)
|
|
||||||
leftPadding: Math.round(18 * DefaultStyle.dp)
|
|
||||||
rightPadding: Math.round(18 * DefaultStyle.dp)
|
|
||||||
|
|
||||||
signal messageDeletionRequested()
|
signal messageDeletionRequested()
|
||||||
|
|
||||||
MouseArea {
|
Avatar {
|
||||||
anchors.fill: parent
|
id: avatar
|
||||||
acceptedButtons: Qt.RightButton
|
visible: mainItem.isFromChatGroup
|
||||||
onClicked: (mouse) => {
|
opacity: mainItem.isRemoteMessage && mainItem.isFirstMessage ? 1 : 0
|
||||||
console.log("message clicked")
|
Layout.preferredWidth: 26 * DefaultStyle.dp
|
||||||
if (mouse.button === Qt.RightButton) {
|
Layout.preferredHeight: 26 * DefaultStyle.dp
|
||||||
optionsMenu.x = mouse.x
|
Layout.alignment: Qt.AlignTop
|
||||||
optionsMenu.open()
|
Layout.topMargin: isFirstMessage ? 16 * DefaultStyle.dp : 0
|
||||||
|
_address: chatMessage ? chatMessage.core.fromAddress : ""
|
||||||
|
}
|
||||||
|
Control.Control {
|
||||||
|
Layout.topMargin: isFirstMessage ? 16 * DefaultStyle.dp : 0
|
||||||
|
Layout.leftMargin: mainItem.isFromChatGroup ? Math.round(9 * DefaultStyle.dp) : 0
|
||||||
|
Layout.preferredWidth: Math.min(implicitWidth, mainItem.maxWidth - avatar.implicitWidth)
|
||||||
|
// Layout.topMargin: name.visible ? Math.round(7 * DefaultStyle.dp) : 0
|
||||||
|
topPadding: Math.round(12 * DefaultStyle.dp)
|
||||||
|
bottomPadding: Math.round(12 * DefaultStyle.dp)
|
||||||
|
leftPadding: Math.round(18 * DefaultStyle.dp)
|
||||||
|
rightPadding: Math.round(18 * DefaultStyle.dp)
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.RightButton
|
||||||
|
onClicked: (mouse) => {
|
||||||
|
console.log("message clicked")
|
||||||
|
if (mouse.button === Qt.RightButton) {
|
||||||
|
optionsMenu.x = mouse.x
|
||||||
|
optionsMenu.open()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Popup {
|
||||||
Popup {
|
id: optionsMenu
|
||||||
id: optionsMenu
|
background: Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
Rectangle {
|
||||||
|
id: popupBackground
|
||||||
|
anchors.fill: parent
|
||||||
|
color: DefaultStyle.grey_0
|
||||||
|
radius: Math.round(16 * DefaultStyle.dp)
|
||||||
|
}
|
||||||
|
MultiEffect {
|
||||||
|
source: popupBackground
|
||||||
|
anchors.fill: popupBackground
|
||||||
|
shadowEnabled: true
|
||||||
|
shadowBlur: 0.1
|
||||||
|
shadowColor: DefaultStyle.grey_1000
|
||||||
|
shadowOpacity: 0.4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
IconLabelButton {
|
||||||
|
//: "Supprimer"
|
||||||
|
text: qsTr("chat_message_delete")
|
||||||
|
icon.source: AppIcons.trashCan
|
||||||
|
spacing: Math.round(10 * DefaultStyle.dp)
|
||||||
|
Layout.fillWidth: true
|
||||||
|
onClicked: {
|
||||||
|
mainItem.messageDeletionRequested()
|
||||||
|
optionsMenu.close()
|
||||||
|
}
|
||||||
|
style: ButtonStyle.noBackgroundRed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
background: Item {
|
background: Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: popupBackground
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: DefaultStyle.grey_0
|
color: mainItem.backgroundColor
|
||||||
radius: Math.round(16 * DefaultStyle.dp)
|
radius: Math.round(16 * DefaultStyle.dp)
|
||||||
}
|
}
|
||||||
MultiEffect {
|
Rectangle {
|
||||||
source: popupBackground
|
visible: mainItem.isFirstMessage && mainItem.isRemoteMessage
|
||||||
anchors.fill: popupBackground
|
anchors.top: parent.top
|
||||||
shadowEnabled: true
|
anchors.left: parent.left
|
||||||
shadowBlur: 0.1
|
width: Math.round(parent.width / 4)
|
||||||
shadowColor: DefaultStyle.grey_1000
|
height: Math.round(parent.height / 4)
|
||||||
shadowOpacity: 0.4
|
color: mainItem.backgroundColor
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
visible: mainItem.isFirstMessage && !mainItem.isRemoteMessage
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
width: Math.round(parent.width / 4)
|
||||||
|
height: Math.round(parent.height / 4)
|
||||||
|
color: mainItem.backgroundColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
contentItem: ColumnLayout {
|
contentItem: ColumnLayout {
|
||||||
IconLabelButton {
|
id: contentLayout
|
||||||
//: "Supprimer"
|
Image {
|
||||||
text: qsTr("chat_message_delete")
|
visible: mainItem.imgUrl != undefined
|
||||||
icon.source: AppIcons.trashCan
|
id: contentimage
|
||||||
spacing: Math.round(10 * DefaultStyle.dp)
|
}
|
||||||
|
Text {
|
||||||
|
visible: modelData.core.text != undefined
|
||||||
|
text: modelData.core.text
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
onClicked: {
|
color: DefaultStyle.main2_700
|
||||||
mainItem.messageDeletionRequested()
|
font {
|
||||||
optionsMenu.close()
|
pixelSize: Typography.p1.pixelSize
|
||||||
|
weight: Typography.p1.weight
|
||||||
}
|
}
|
||||||
style: ButtonStyle.noBackgroundRed
|
|
||||||
}
|
}
|
||||||
}
|
Text {
|
||||||
}
|
Layout.alignment: Qt.AlignRight
|
||||||
|
text: UtilsCpp.formatDate(modelData.core.timestamp, true, false)
|
||||||
background: Item {
|
color: DefaultStyle.main2_500main
|
||||||
anchors.fill: parent
|
font {
|
||||||
Rectangle {
|
pixelSize: Typography.p3.pixelSize
|
||||||
anchors.fill: parent
|
weight: Typography.p3.weight
|
||||||
color: mainItem.backgroundColor
|
}
|
||||||
radius: Math.round(16 * DefaultStyle.dp)
|
|
||||||
}
|
|
||||||
Rectangle {
|
|
||||||
visible: mainItem.isFirstMessage && mainItem.isRemoteMessage
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
width: Math.round(parent.width / 4)
|
|
||||||
height: Math.round(parent.height / 4)
|
|
||||||
color: mainItem.backgroundColor
|
|
||||||
}
|
|
||||||
Rectangle {
|
|
||||||
visible: mainItem.isFirstMessage && !mainItem.isRemoteMessage
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: parent.right
|
|
||||||
width: Math.round(parent.width / 4)
|
|
||||||
height: Math.round(parent.height / 4)
|
|
||||||
color: mainItem.backgroundColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
contentItem: ColumnLayout {
|
|
||||||
id: contentLayout
|
|
||||||
Image {
|
|
||||||
visible: mainItem.imgUrl != undefined
|
|
||||||
id: contentimage
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
visible: mainItem.contentText != undefined
|
|
||||||
text: mainItem.contentText
|
|
||||||
Layout.fillWidth: true
|
|
||||||
color: DefaultStyle.main2_700
|
|
||||||
font {
|
|
||||||
pixelSize: Typography.p1.pixelSize
|
|
||||||
weight: Typography.p1.weight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
text: UtilsCpp.formatDate(modelData.core.timestamp, true, false)
|
|
||||||
color: DefaultStyle.main2_500main
|
|
||||||
font {
|
|
||||||
pixelSize: Typography.p3.pixelSize
|
|
||||||
weight: Typography.p3.weight
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,15 @@ import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils
|
||||||
ListView {
|
ListView {
|
||||||
id: mainItem
|
id: mainItem
|
||||||
property ChatGui chat
|
property ChatGui chat
|
||||||
spacing: Math.round(20 * DefaultStyle.dp)
|
property color backgroundColor
|
||||||
|
spacing: Math.round(4 * DefaultStyle.dp)
|
||||||
|
|
||||||
Component.onCompleted: positionViewAtEnd()
|
Component.onCompleted: positionViewAtEnd()
|
||||||
|
|
||||||
onCountChanged: positionViewAtEnd();
|
onCountChanged: positionViewAtEnd()
|
||||||
|
|
||||||
model: ChatMessageProxy {
|
model: ChatMessageProxy {
|
||||||
|
id: chatMessageProxy
|
||||||
chatGui: mainItem.chat
|
chatGui: mainItem.chat
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,17 +28,49 @@ ListView {
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: ChatMessage {
|
delegate: ChatMessage {
|
||||||
id: chatMessage
|
chatMessage: modelData
|
||||||
width: Math.min(implicitWidth, Math.round(mainItem.width * (3/4)))
|
property real maxWidth: Math.round(mainItem.width * (3/4))
|
||||||
// height: childrenRect.height
|
// height: childrenRect.height
|
||||||
|
// width: childrenRect.width
|
||||||
|
property var previousIndex: index - 1
|
||||||
|
property var previousFromAddress: chatMessageProxy.getChatMessageAtIndex(index-1)?.core.fromAddress
|
||||||
backgroundColor: isRemoteMessage ? DefaultStyle.main2_100 : DefaultStyle.main1_100
|
backgroundColor: isRemoteMessage ? DefaultStyle.main2_100 : DefaultStyle.main1_100
|
||||||
contentText: modelData.core.text
|
isFirstMessage: !previousFromAddress || previousFromAddress !== modelData.core.fromAddress
|
||||||
isFirstMessage: true
|
|
||||||
isRemoteMessage: modelData.core.isRemoteMessage
|
|
||||||
anchors.right: !isRemoteMessage && parent
|
anchors.right: !isRemoteMessage && parent
|
||||||
? parent.right
|
? parent.right
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
onMessageDeletionRequested: modelData.core.lDelete()
|
onMessageDeletionRequested: modelData.core.lDelete()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
footerPositioning: ListView.OverlayFooter
|
||||||
|
footer: Control.Control {
|
||||||
|
visible: composeLayout.composingName !== ""
|
||||||
|
width: mainItem.width
|
||||||
|
z: mainItem.z + 2
|
||||||
|
topPadding: Math.round(5 * DefaultStyle.dp)
|
||||||
|
bottomPadding: Math.round(5 * DefaultStyle.dp)
|
||||||
|
background: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: mainItem.panelColor
|
||||||
|
}
|
||||||
|
contentItem: RowLayout {
|
||||||
|
id: composeLayout
|
||||||
|
property string composingName: mainItem.chat.core.composingName
|
||||||
|
Avatar {
|
||||||
|
Layout.preferredWidth: Math.round(20 * DefaultStyle.dp)
|
||||||
|
Layout.preferredHeight: Math.round(20 * DefaultStyle.dp)
|
||||||
|
_address: mainItem.chat.core.composingAddress
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font {
|
||||||
|
pixelSize: Typography.p3.pixelSize
|
||||||
|
weight: Typography.p3.weight
|
||||||
|
}
|
||||||
|
//: %1 is writing…
|
||||||
|
text: qsTr("%1 est en train d'écrire…").arg(composeLayout.composingName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -84,7 +84,6 @@ Loader{
|
||||||
Connections{
|
Connections{
|
||||||
target: mainItem
|
target: mainItem
|
||||||
onHaveAvatarChanged: {
|
onHaveAvatarChanged: {
|
||||||
console.log("have avatar changed", mainItem.haveAvatar, mainItem._address)
|
|
||||||
stackView.replace(mainItem.haveAvatar ? avatar : initials, StackView.Immediate)}
|
stackView.replace(mainItem.haveAvatar ? avatar : initials, StackView.Immediate)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,7 @@ FocusScope {
|
||||||
property real itemsRightMargin: Math.round(39 * DefaultStyle.dp)
|
property real itemsRightMargin: Math.round(39 * DefaultStyle.dp)
|
||||||
|
|
||||||
property var displayName: searchResultItem.core.fullName
|
property var displayName: searchResultItem.core.fullName
|
||||||
property string initial: displayName ? displayName[0].toLocaleLowerCase(
|
property string initial: displayName ? displayName[0].toLocaleLowerCase(ConstantsCpp.DefaultLocale) : ''
|
||||||
ConstantsCpp.DefaultLocale) : ''
|
|
||||||
|
|
||||||
signal clicked(var mouse)
|
signal clicked(var mouse)
|
||||||
signal contactDeletionRequested(FriendGui contact)
|
signal contactDeletionRequested(FriendGui contact)
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ RowLayout {
|
||||||
ChatMessagesListView {
|
ChatMessagesListView {
|
||||||
id: chatMessagesListView
|
id: chatMessagesListView
|
||||||
height: contentHeight
|
height: contentHeight
|
||||||
|
backgroundColor: panelColor
|
||||||
width: parent.width - anchors.leftMargin - anchors.rightMargin
|
width: parent.width - anchors.leftMargin - anchors.rightMargin
|
||||||
chat: mainItem.chat
|
chat: mainItem.chat
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
|
@ -88,7 +89,6 @@ RowLayout {
|
||||||
anchors.bottom: messageSender.top
|
anchors.bottom: messageSender.top
|
||||||
anchors.leftMargin: Math.round(18 * DefaultStyle.dp)
|
anchors.leftMargin: Math.round(18 * DefaultStyle.dp)
|
||||||
anchors.rightMargin: Math.round(18 * DefaultStyle.dp)
|
anchors.rightMargin: Math.round(18 * DefaultStyle.dp)
|
||||||
anchors.bottomMargin: Math.round(18 * DefaultStyle.dp)
|
|
||||||
Control.ScrollBar.vertical: scrollbar
|
Control.ScrollBar.vertical: scrollbar
|
||||||
},
|
},
|
||||||
ScrollBar {
|
ScrollBar {
|
||||||
|
|
@ -106,13 +106,22 @@ RowLayout {
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
height: 79 * DefaultStyle.dp
|
|
||||||
leftPadding: Math.round(15 * DefaultStyle.dp)
|
leftPadding: Math.round(15 * DefaultStyle.dp)
|
||||||
rightPadding: Math.round(15 * DefaultStyle.dp)
|
rightPadding: Math.round(15 * DefaultStyle.dp)
|
||||||
topPadding: Math.round(16 * DefaultStyle.dp)
|
topPadding: Math.round(24 * DefaultStyle.dp)
|
||||||
bottomPadding: Math.round(16 * DefaultStyle.dp)
|
bottomPadding: Math.round(16 * DefaultStyle.dp)
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
color: DefaultStyle.grey_100
|
color: DefaultStyle.grey_100
|
||||||
|
MediumButton {
|
||||||
|
id: expandButton
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: Math.round(4 * DefaultStyle.dp)
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
style: ButtonStyle.noBackgroundOrange
|
||||||
|
icon.source: checked ? AppIcons.downArrow : AppIcons.upArrow
|
||||||
|
checkable: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
spacing: Math.round(20 * DefaultStyle.dp)
|
spacing: Math.round(20 * DefaultStyle.dp)
|
||||||
|
|
@ -135,19 +144,62 @@ RowLayout {
|
||||||
}
|
}
|
||||||
Control.Control {
|
Control.Control {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: Math.round(48 * DefaultStyle.dp)
|
leftPadding: Math.round(15 * DefaultStyle.dp)
|
||||||
|
rightPadding: Math.round(15 * DefaultStyle.dp)
|
||||||
|
topPadding: Math.round(16 * DefaultStyle.dp)
|
||||||
|
bottomPadding: Math.round(16 * DefaultStyle.dp)
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
id: inputBackground
|
id: inputBackground
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: Math.round(30 * DefaultStyle.dp)
|
radius: Math.round(35 * DefaultStyle.dp)
|
||||||
color: DefaultStyle.grey_0
|
color: DefaultStyle.grey_0
|
||||||
}
|
}
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
TextArea {
|
Flickable {
|
||||||
id: sendingTextArea
|
id: sendingAreaFlickable
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.preferredWidth: parent.width - stackButton.width
|
Layout.preferredWidth: parent.width - stackButton.width
|
||||||
|
Layout.preferredHeight: Math.min(Math.round(60 * DefaultStyle.dp), contentHeight)
|
||||||
|
Binding {
|
||||||
|
target: sendingAreaFlickable
|
||||||
|
when: expandButton.checked
|
||||||
|
property: "Layout.preferredHeight"
|
||||||
|
value: Math.round(250 * DefaultStyle.dp)
|
||||||
|
restoreMode: Binding.RestoreBindingOrValue
|
||||||
|
}
|
||||||
|
Layout.fillHeight: true
|
||||||
|
contentHeight: sendingTextArea.contentHeight
|
||||||
|
contentWidth: width
|
||||||
|
|
||||||
|
function ensureVisible(r) {
|
||||||
|
if (contentX >= r.x)
|
||||||
|
contentX = r.x;
|
||||||
|
else if (contentX+width <= r.x+r.width)
|
||||||
|
contentX = r.x+r.width-width;
|
||||||
|
if (contentY >= r.y)
|
||||||
|
contentY = r.y;
|
||||||
|
else if (contentY+height <= r.y+r.height)
|
||||||
|
contentY = r.y+r.height-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
id: sendingTextArea
|
||||||
|
width: parent.width
|
||||||
|
height: sendingAreaFlickable.height
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
//: Say something… : placeholder text for sending message text area
|
||||||
|
placeholderText: qsTr("Dites quelque chose…")
|
||||||
|
placeholderTextColor: DefaultStyle.main2_400
|
||||||
|
onCursorRectangleChanged: sendingAreaFlickable.ensureVisible(cursorRectangle)
|
||||||
|
property string previousText
|
||||||
|
Component.onCompleted: previousText = text
|
||||||
|
onTextChanged: {
|
||||||
|
if (previousText === "" && text !== "") {
|
||||||
|
mainItem.chat.core.lCompose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
StackLayout {
|
StackLayout {
|
||||||
id: stackButton
|
id: stackButton
|
||||||
|
|
@ -163,7 +215,8 @@ RowLayout {
|
||||||
style: ButtonStyle.noBackgroundOrange
|
style: ButtonStyle.noBackgroundOrange
|
||||||
icon.source: AppIcons.paperPlaneRight
|
icon.source: AppIcons.paperPlaneRight
|
||||||
onClicked: {
|
onClicked: {
|
||||||
console.log("TODO : send message")
|
mainItem.chat.core.lSendTextMessage(sendingTextArea.text)
|
||||||
|
sendingTextArea.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ AbstractMainPage {
|
||||||
property string remoteAddress
|
property string remoteAddress
|
||||||
onRemoteAddressChanged: console.log("ChatPage : remote address changed :", remoteAddress)
|
onRemoteAddressChanged: console.log("ChatPage : remote address changed :", remoteAddress)
|
||||||
property var remoteChatObj: UtilsCpp.getChatForAddress(remoteAddress)
|
property var remoteChatObj: UtilsCpp.getChatForAddress(remoteAddress)
|
||||||
property ChatGui remoteChat: remoteChatObj ? remoteChatObj.value : null
|
property ChatGui remoteChat: remoteChatObj && remoteChatObj.value ? remoteChatObj.value : null
|
||||||
onRemoteChatChanged: if (remoteChat) selectedChatGui = remoteChat
|
onRemoteChatChanged: if (remoteChat) selectedChatGui = remoteChat
|
||||||
|
|
||||||
onSelectedChatGuiChanged: {
|
onSelectedChatGuiChanged: {
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,13 @@ QtObject {
|
||||||
weight: Math.min(Math.round(800 * DefaultStyle.dp), 1000)
|
weight: Math.min(Math.round(800 * DefaultStyle.dp), 1000)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Text/P4 - Xsmall paragraph text
|
||||||
|
property font p4: Qt.font( {
|
||||||
|
family: DefaultStyle.defaultFont,
|
||||||
|
pixelSize: Math.round(10 * DefaultStyle.dp),
|
||||||
|
weight: Math.min(Math.round(300 * DefaultStyle.dp), 1000)
|
||||||
|
})
|
||||||
|
|
||||||
// Text/P3 - Reduced paragraph text
|
// Text/P3 - Reduced paragraph text
|
||||||
property font p3: Qt.font( {
|
property font p3: Qt.font( {
|
||||||
family: DefaultStyle.defaultFont,
|
family: DefaultStyle.defaultFont,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue