enlarge image size when single in message #LINQT-2008

This commit is contained in:
Gaelle Braud 2025-10-01 10:34:03 +02:00
parent 580819df3a
commit 924224abc5
9 changed files with 175 additions and 40 deletions

View file

@ -57,16 +57,16 @@ void ChatMessageContentProxy::setChatMessageGui(ChatMessageGui *chat) {
getListModel<ChatMessageContentList>()->setChatMessageGui(chat); getListModel<ChatMessageContentList>()->setChatMessageGui(chat);
} }
// ChatMessageGui *ChatMessageContentProxy::getChatMessageAtIndex(int i) { ChatMessageContentGui *ChatMessageContentProxy::getChatMessageContentAtIndex(int i) {
// auto model = getListModel<ChatMessageContentList>(); auto model = getListModel<ChatMessageContentList>();
// auto sourceIndex = mapToSource(index(i, 0)).row(); auto sourceIndex = mapToSource(index(i, 0)).row();
// if (model) { if (model) {
// auto chat = model->getAt<ChatMessageCore>(sourceIndex); auto chat = model->getAt<ChatMessageContentCore>(sourceIndex);
// if (chat) return new ChatMessageGui(chat); if (chat) return new ChatMessageContentGui(chat);
// else return nullptr; else return nullptr;
// } }
// return nullptr; return nullptr;
// } }
void ChatMessageContentProxy::addFiles(const QStringList &paths) { void ChatMessageContentProxy::addFiles(const QStringList &paths) {
auto model = getListModel<ChatMessageContentList>(); auto model = getListModel<ChatMessageContentList>();
@ -99,8 +99,5 @@ bool ChatMessageContentProxy::SortFilterList::filterAcceptsRow(int sourceRow, co
bool ChatMessageContentProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft, bool ChatMessageContentProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft,
const QModelIndex &sourceRight) const { const QModelIndex &sourceRight) const {
auto l = getItemAtSource<ChatMessageContentList, ChatMessageCore>(sourceLeft.row()); return true;
auto r = getItemAtSource<ChatMessageContentList, ChatMessageCore>(sourceRight.row());
if (l && r) return l->getTimestamp() <= r->getTimestamp();
else return true;
} }

View file

@ -45,6 +45,8 @@ public:
ChatMessageGui *getChatMessageGui(); ChatMessageGui *getChatMessageGui();
void setChatMessageGui(ChatMessageGui *chat); void setChatMessageGui(ChatMessageGui *chat);
Q_INVOKABLE ChatMessageContentGui *getChatMessageContentAtIndex(int i);
void setSourceModel(QAbstractItemModel *sourceModel) override; void setSourceModel(QAbstractItemModel *sourceModel) override;
Q_INVOKABLE void addFiles(const QStringList &paths); Q_INVOKABLE void addFiles(const QStringList &paths);

View file

@ -114,8 +114,8 @@ public:
// Max image size in bytes. (1Mb) // Max image size in bytes. (1Mb)
static constexpr qint64 MaxImageSize = 1024000; // In Bytes. static constexpr qint64 MaxImageSize = 1024000; // In Bytes.
static constexpr qint64 FileSizeLimit = 524288000; // In Bytes. static constexpr qint64 FileSizeLimit = 524288000; // In Bytes.
static constexpr int ThumbnailImageFileWidth = 100; static constexpr int ThumbnailImageFileWidth = 285;
static constexpr int ThumbnailImageFileHeight = 100; static constexpr int ThumbnailImageFileHeight = 345;
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// LINPHONE // LINPHONE

View file

@ -67,6 +67,8 @@ list(APPEND _LINPHONEAPP_QML_FILES
view/Control/Display/Chat/Event.qml view/Control/Display/Chat/Event.qml
view/Control/Display/Chat/EphemeralEvent.qml view/Control/Display/Chat/EphemeralEvent.qml
view/Control/Display/Chat/FileView.qml view/Control/Display/Chat/FileView.qml
view/Control/Display/Chat/ImageFileView.qml
view/Control/Display/Chat/AnimatedImageFileView.qml
view/Control/Display/Contact/Avatar.qml view/Control/Display/Contact/Avatar.qml
view/Control/Display/Contact/Contact.qml view/Control/Display/Contact/Contact.qml
view/Control/Display/Contact/Presence.qml view/Control/Display/Contact/Presence.qml

View file

@ -1,6 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import QtQml.Models import QtQml.Models
import QtQuick.Controls.Basic as Control
import Linphone import Linphone
import UtilsCpp import UtilsCpp
@ -8,7 +9,7 @@ import UtilsCpp
// ============================================================================= // =============================================================================
GridLayout { GridLayout {
id: mainItem id: mainItem
property ChatMessageGui chatMessageGui: null property ChatMessageContentProxy proxyModel
property bool isHoveringFile: false property bool isHoveringFile: false
property int itemCount: delModel.count property int itemCount: delModel.count
property int itemWidth: Math.round(95 * DefaultStyle.dp) property int itemWidth: Math.round(95 * DefaultStyle.dp)
@ -40,15 +41,10 @@ GridLayout {
return bestCols; return bestCols;
} }
Repeater { Repeater {
id: delModel id: delModel
model: ChatMessageContentProxy { model: mainItem.proxyModel
id: contentProxy
filterType: ChatMessageContentProxy.FilterContentType.File
chatMessageGui: mainItem.chatMessageGui
}
delegate: FileView { delegate: FileView {
id: avatarCell id: avatarCell
contentGui: modelData contentGui: modelData

View file

@ -0,0 +1,56 @@
import QtQuick
import QtQuick.Controls as Control
import QtQuick.Layouts
import QtMultimedia
import Linphone
import UtilsCpp
import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils
// =============================================================================
// ---------------------------------------------------------------------
// Separated file to show a single image bigger in chat message
// The FileView file does not allow that as it is a Loader and the image
// is reloaded everytime the message becomes visible again. It causes the
// chat message not to be able to adapt its size according to the painted
// size of the image
// ---------------------------------------------------------------------
AnimatedImage {
id: mainItem
property ChatMessageContentGui contentGui
mipmap: false//SettingsModel.mipmapEnabled
autoTransform: true
fillMode: Image.PreserveAspectFit
source: contentGui && UtilsCpp.isAnimatedImage(contentGui.core.filePath) ? ('file:/'+ contentGui.core.filePath) : ""
states: State {
name: 'hovered'
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
propagateComposedEvents: true
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
// Changing cursor in MouseArea seems not to work with the Loader
// Use override cursor for this case
onContainsMouseChanged: {
if (containsMouse) UtilsCpp.setGlobalCursor(Qt.PointingHandCursor)
else UtilsCpp.restoreGlobalCursor()
mainItem.state = containsMouse ? 'hovered' : ''
}
onPressed: (mouse) => {
mouse.accepted = true
// if(SettingsModel.isVfsEncrypted){
// window.attachVirtualWindow(Utils.buildCommonDialogUri('FileViewDialog'), {
// contentGui: mainItem.contentGui,
// }, function (status) {
// })
// }else
mainItem.contentGui.core.lOpenFile()
}
}
}

View file

@ -3,6 +3,7 @@ import QtQuick.Effects
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Controls.Basic as Control import QtQuick.Controls.Basic as Control
import Linphone import Linphone
import UtilsCpp
// ============================================================================= // =============================================================================
// Simple content display without reply and forward. These modules need to be splitted because of cyclic dependencies. // Simple content display without reply and forward. These modules need to be splitted because of cyclic dependencies.
@ -29,12 +30,17 @@ ColumnLayout {
spacing: Math.round(5 * DefaultStyle.dp) spacing: Math.round(5 * DefaultStyle.dp)
property int padding: Math.round(10 * DefaultStyle.dp) property int padding: Math.round(10 * DefaultStyle.dp)
property ChatMessageContentProxy filescontentProxy: ChatMessageContentProxy {
filterType: ChatMessageContentProxy.FilterContentType.File
chatMessageGui: mainItem.chatMessageGui
}
// VOICE MESSAGES // VOICE MESSAGES
Repeater { Repeater {
id: messagesVoicesList id: messagesVoicesList
visible: count > 0 visible: count > 0
model: ChatMessageContentProxy{ model: ChatMessageContentProxy {
filterType: ChatMessageContentProxy.FilterContentType.Voice filterType: ChatMessageContentProxy.FilterContentType.Voice
chatMessageGui: mainItem.chatMessageGui chatMessageGui: mainItem.chatMessageGui
} }
@ -70,15 +76,39 @@ ColumnLayout {
onMouseEvent: (event) => mainItem.mouseEvent(event) onMouseEvent: (event) => mainItem.mouseEvent(event)
} }
} }
// SINGLE FILE
ImageFileView {
id: singleImageFile
visible: mainItem.filescontentProxy.count === 1 && source !== "" && UtilsCpp.isImage(contentGui.core.filePath)
contentGui: mainItem.filescontentProxy.count === 1
? mainItem.filescontentProxy.getChatMessageContentAtIndex(0)
: null
width: Math.round(285 * DefaultStyle.dp)
Layout.alignment: Qt.AlignHCenter
fillMode: Image.PreserveAspectFit
}
AnimatedImageFileView {
id: singleAnimatedImageFile
visible: mainItem.filescontentProxy.count === 1 && source !== "" && UtilsCpp.isAnimatedImage(contentGui.core.filePath)
contentGui: mainItem.filescontentProxy.count === 1
? mainItem.filescontentProxy.getChatMessageContentAtIndex(0)
: null
Layout.preferredWidth: Math.round(285 * DefaultStyle.dp)
Layout.preferredHeight: paintedHeight
Layout.alignment: Qt.AlignHCenter
fillMode: Image.PreserveAspectFit
}
// FILES // FILES
ChatFilesGridLayout { ChatFilesGridLayout {
id: messageFilesList id: messageFilesList
visible: itemCount > 0 visible: mainItem.filescontentProxy.count > 0
Layout.fillWidth: true && !singleImageFile.visible
&& !singleAnimatedImageFile.visible
Layout.fillWidth: visible
Layout.fillHeight: visible
maxWidth: Math.round(115*3 * DefaultStyle.dp) maxWidth: Math.round(115*3 * DefaultStyle.dp)
Layout.fillHeight: true // Layout.fillHeight: true
// Layout.preferredHeight: contentHeight proxyModel: visible ? mainItem.filescontentProxy : null
chatMessageGui: mainItem.chatMessageGui
// onIsHoveringFileChanged: mainItem.isFileHoveringChanged(isHoveringFile) // onIsHoveringFileChanged: mainItem.isFileHoveringChanged(isHoveringFile)
// borderWidth: mainItem.fileBorderWidth // borderWidth: mainItem.fileBorderWidth
// property int availableSection: mainItem.availableWidth / mainItem.filesBestWidth // property int availableSection: mainItem.availableWidth / mainItem.filesBestWidth

View file

@ -26,8 +26,6 @@ Item {
property bool isImage: UtilsCpp.isImage(filePath) property bool isImage: UtilsCpp.isImage(filePath)
property bool isPdf: UtilsCpp.isPdf(filePath) property bool isPdf: UtilsCpp.isPdf(filePath)
property bool isThumbnail: isVideo || isImage || isPdf property bool isThumbnail: isVideo || isImage || isPdf
property int overriddenWidth
property int overriddenHeight
// property to change default view display // property to change default view display
property bool showAsSquare: true property bool showAsSquare: true
// default image // default image
@ -40,6 +38,7 @@ Item {
? AppIcons.fileText ? AppIcons.fileText
: AppIcons.file : AppIcons.file
: '' : ''
property var thumbnailFillMode: Image.PreserveAspectCrop
Connections { Connections {
enabled: contentGui enabled: contentGui
@ -60,12 +59,9 @@ Item {
id: thumbnailImage id: thumbnailImage
Item { Item {
id: thumbnailSource id: thumbnailSource
property bool isVideo: UtilsCpp.isVideo(mainItem.filePath)
property bool isImage: UtilsCpp.isImage(mainItem.filePath)
property bool isPdf: UtilsCpp.isPdf(mainItem.filePath)
Image { Image {
anchors.fill: parent anchors.fill: parent
visible: thumbnailSource.isPdf visible: mainItem.isPdf
source: AppIcons.filePdf source: AppIcons.filePdf
sourceSize.width: mainItem.width sourceSize.width: mainItem.width
sourceSize.height: mainItem.height sourceSize.height: mainItem.height
@ -82,24 +78,24 @@ Item {
} }
Image { Image {
id: image id: image
visible: thumbnailSource.isImage && status !== Image.Loading visible: mainItem.isImage && status !== Image.Loading
mipmap: false//SettingsModel.mipmapEnabled mipmap: false//SettingsModel.mipmapEnabled
source: mainItem.thumbnail source: mainItem.thumbnail
sourceSize.width: mainItem.width sourceSize.width: mainItem.width
sourceSize.height: mainItem.height sourceSize.height: mainItem.height
autoTransform: true autoTransform: true
fillMode: Image.PreserveAspectCrop
anchors.fill: parent anchors.fill: parent
fillMode: mainItem.thumbnailFillMode
} }
Rectangle { Rectangle {
visible: thumbnailSource.isVideo visible: mainItem.isVideo
color: DefaultStyle.grey_1000 color: DefaultStyle.grey_1000
anchors.fill: parent anchors.fill: parent
Video { Video {
id: videoThumbnail id: videoThumbnail
anchors.fill: parent anchors.fill: parent
position: 100 position: 100
source: "file:///" + mainItem.filePath source: mainItem.isVideo ? "file:///" + mainItem.filePath : ""
fillMode: playbackState === MediaPlayer.PlayingState ? VideoOutput.PreserveAspectFit : VideoOutput.PreserveAspectCrop fillMode: playbackState === MediaPlayer.PlayingState ? VideoOutput.PreserveAspectFit : VideoOutput.PreserveAspectCrop
MouseArea { MouseArea {
propagateComposedEvents: false propagateComposedEvents: false

View file

@ -0,0 +1,56 @@
import QtQuick
import QtQuick.Controls as Control
import QtQuick.Layouts
import QtMultimedia
import Linphone
import UtilsCpp
import 'qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js' as Utils
// =============================================================================
// ---------------------------------------------------------------------
// Separated file to show a single image bigger in chat message
// The FileView file does not allow that as it is a Loader and the image
// is reloaded everytime the message becomes visible again. It causes the
// chat message not to be able to adapt its size according to the painted
// size of the image
// ---------------------------------------------------------------------
Image {
id: mainItem
property ChatMessageContentGui contentGui
mipmap: false//SettingsModel.mipmapEnabled
autoTransform: true
fillMode: Image.PreserveAspectFit
source: contentGui && contentGui.core.thumbnail || ""
states: State {
name: 'hovered'
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
propagateComposedEvents: true
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
// Changing cursor in MouseArea seems not to work with the Loader
// Use override cursor for this case
onContainsMouseChanged: {
if (containsMouse) UtilsCpp.setGlobalCursor(Qt.PointingHandCursor)
else UtilsCpp.restoreGlobalCursor()
mainItem.state = containsMouse ? 'hovered' : ''
}
onPressed: (mouse) => {
mouse.accepted = true
// if(SettingsModel.isVfsEncrypted){
// window.attachVirtualWindow(Utils.buildCommonDialogUri('FileViewDialog'), {
// contentGui: mainItem.contentGui,
// }, function (status) {
// })
// }else
mainItem.contentGui.core.lOpenFile()
}
}
}