mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-24 03:58:49 +03:00
c9f1a449d8
Qt6 changed the mouse scroll wheel handling for QtQuick to a type that mimics how touch pads/screens work, which most people find feels very poor. KDE fixes this by creating a custom type which re-implements the QtWidgets handling (see https://invent.kde.org/frameworks/kirigami/-/merge_requests/415). On Matrix Nico has expressed a desire not to have to deal with compiling Kirigami for Windows and Mac, which is understandable. Linux users on the other hand almost always have kirigami available in their package repos which sidesteps that particular issue. We can search for Kirigami at build time and if present define a QML context property to allow it to be used, which should fix this issue for Linux users at least. Helps with nheko-reborn/nheko#1819 (which won't be completely resolved until this is working for Windows and Mac as well). Signed-off-by: Reilly Brogan <reilly@reillybrogan.com>
340 lines
12 KiB
QML
340 lines
12 KiB
QML
// SPDX-FileCopyrightText: Nheko Contributors
|
|
//
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
import ".."
|
|
import "../components"
|
|
import Qt.labs.platform 1.1
|
|
import QtQuick 2.12
|
|
import QtQuick.Controls 2.12
|
|
import QtQuick.Layouts 1.12
|
|
import im.nheko 1.0
|
|
|
|
ApplicationWindow {
|
|
id: win
|
|
|
|
property int avatarSize: Math.ceil(fontMetrics.lineSpacing * 2.3)
|
|
property SingleImagePackModel imagePack
|
|
property int currentImageIndex: -1
|
|
readonly property int stickerDim: 128
|
|
readonly property int stickerDimPad: 128 + Nheko.paddingSmall
|
|
|
|
title: qsTr("Editing image pack")
|
|
height: 600
|
|
width: 600
|
|
color: palette.base
|
|
modality: Qt.WindowModal
|
|
flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
|
|
|
|
AdaptiveLayout {
|
|
id: adaptiveView
|
|
|
|
anchors.fill: parent
|
|
singlePageMode: false
|
|
pageIndex: 0
|
|
|
|
AdaptiveLayoutElement {
|
|
id: packlistC
|
|
|
|
visible: Settings.groupView
|
|
minimumWidth: 200
|
|
collapsedWidth: 200
|
|
preferredWidth: 300
|
|
maximumWidth: 300
|
|
clip: true
|
|
|
|
ListView {
|
|
//required property bool isEmote
|
|
//required property bool isSticker
|
|
|
|
model: imagePack
|
|
|
|
Loader {
|
|
source: NHEKO_USE_KIRIGAMI ? "../components/KirigamiWheelHandler.qml" : ""
|
|
}
|
|
|
|
header: AvatarListTile {
|
|
title: imagePack.packname
|
|
avatarUrl: imagePack.avatarUrl
|
|
roomid: imagePack.statekey
|
|
subtitle: imagePack.statekey
|
|
index: -1
|
|
selectedIndex: currentImageIndex
|
|
|
|
TapHandler {
|
|
onSingleTapped: currentImageIndex = -1
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.left: parent.left
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
height: parent.height - Nheko.paddingSmall * 2
|
|
width: 3
|
|
color: palette.highlight
|
|
}
|
|
|
|
}
|
|
|
|
footer: Button {
|
|
onClicked: addFilesDialog.open()
|
|
width: ListView.view.width
|
|
text: qsTr("Add images")
|
|
|
|
FileDialog {
|
|
id: addFilesDialog
|
|
|
|
folder: StandardPaths.writableLocation(StandardPaths.PicturesLocation)
|
|
fileMode: FileDialog.OpenFiles
|
|
nameFilters: [qsTr("Images (*.png *.webp *.gif *.jpg *.jpeg)")]
|
|
title: qsTr("Select images for pack")
|
|
acceptLabel: qsTr("Add to pack")
|
|
onAccepted: imagePack.addStickers(files)
|
|
}
|
|
|
|
}
|
|
|
|
delegate: AvatarListTile {
|
|
id: packItem
|
|
|
|
property color background: palette.window
|
|
property color importantText: palette.text
|
|
property color unimportantText: palette.buttonText
|
|
property color bubbleBackground: palette.highlight
|
|
property color bubbleText: palette.highlightedText
|
|
required property string shortCode
|
|
required property string url
|
|
required property string body
|
|
|
|
title: shortCode
|
|
subtitle: body
|
|
avatarUrl: url
|
|
selectedIndex: currentImageIndex
|
|
crop: false
|
|
|
|
TapHandler {
|
|
onSingleTapped: currentImageIndex = index
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AdaptiveLayoutElement {
|
|
id: packinfoC
|
|
|
|
Rectangle {
|
|
color: palette.window
|
|
|
|
GridLayout {
|
|
anchors.fill: parent
|
|
anchors.margins: Nheko.paddingMedium
|
|
visible: currentImageIndex == -1
|
|
enabled: visible
|
|
columns: 2
|
|
rowSpacing: Nheko.paddingLarge
|
|
|
|
Avatar {
|
|
Layout.columnSpan: 2
|
|
url: imagePack.avatarUrl.replace("mxc://", "image://MxcImage/")
|
|
displayName: imagePack.packname
|
|
roomid: imagePack.statekey
|
|
Layout.preferredHeight: 130
|
|
Layout.preferredWidth: 130
|
|
crop: false
|
|
Layout.alignment: Qt.AlignHCenter
|
|
|
|
ImageButton {
|
|
hoverEnabled: true
|
|
ToolTip.visible: hovered
|
|
ToolTip.text: qsTr("Change the overview image for this pack")
|
|
anchors.left: parent.left
|
|
anchors.top: parent.top
|
|
anchors.leftMargin: Nheko.paddingMedium
|
|
anchors.topMargin: Nheko.paddingMedium
|
|
image: ":/icons/icons/ui/edit.svg"
|
|
onClicked: addAvatarDialog.open()
|
|
|
|
FileDialog {
|
|
id: addAvatarDialog
|
|
|
|
folder: StandardPaths.writableLocation(StandardPaths.PicturesLocation)
|
|
fileMode: FileDialog.OpenFile
|
|
nameFilters: [qsTr("Overview Image (*.png *.webp *.jpg *.jpeg)")]
|
|
title: qsTr("Select overview image for pack")
|
|
onAccepted: imagePack.setAvatar(file)
|
|
}
|
|
}
|
|
}
|
|
|
|
MatrixTextField {
|
|
id: statekeyField
|
|
|
|
visible: imagePack.roomid
|
|
Layout.fillWidth: true
|
|
Layout.columnSpan: 2
|
|
label: qsTr("State key")
|
|
text: imagePack.statekey
|
|
onTextEdited: imagePack.statekey = text
|
|
}
|
|
|
|
MatrixTextField {
|
|
Layout.fillWidth: true
|
|
Layout.columnSpan: 2
|
|
label: qsTr("Packname")
|
|
text: imagePack.packname
|
|
onTextEdited: imagePack.packname = text
|
|
}
|
|
|
|
MatrixTextField {
|
|
Layout.fillWidth: true
|
|
Layout.columnSpan: 2
|
|
label: qsTr("Attribution")
|
|
text: imagePack.attribution
|
|
onTextEdited: imagePack.attribution = text
|
|
}
|
|
|
|
MatrixText {
|
|
Layout.margins: statekeyField.textPadding
|
|
font.weight: Font.DemiBold
|
|
font.letterSpacing: font.pixelSize * 0.02
|
|
text: qsTr("Use as Emoji")
|
|
}
|
|
|
|
ToggleButton {
|
|
checked: imagePack.isEmotePack
|
|
onCheckedChanged: imagePack.isEmotePack = checked
|
|
Layout.alignment: Qt.AlignRight
|
|
}
|
|
|
|
MatrixText {
|
|
Layout.margins: statekeyField.textPadding
|
|
font.weight: Font.DemiBold
|
|
font.letterSpacing: font.pixelSize * 0.02
|
|
text: qsTr("Use as Sticker")
|
|
}
|
|
|
|
ToggleButton {
|
|
checked: imagePack.isStickerPack
|
|
onCheckedChanged: imagePack.isStickerPack = checked
|
|
Layout.alignment: Qt.AlignRight
|
|
}
|
|
|
|
Item {
|
|
Layout.columnSpan: 2
|
|
Layout.fillHeight: true
|
|
}
|
|
|
|
}
|
|
|
|
GridLayout {
|
|
anchors.fill: parent
|
|
anchors.margins: Nheko.paddingMedium
|
|
visible: currentImageIndex >= 0
|
|
enabled: visible
|
|
columns: 2
|
|
rowSpacing: Nheko.paddingLarge
|
|
|
|
Avatar {
|
|
Layout.columnSpan: 2
|
|
url: imagePack.data(imagePack.index(currentImageIndex, 0), SingleImagePackModel.Url).replace("mxc://", "image://MxcImage/") + "?scale"
|
|
displayName: imagePack.data(imagePack.index(currentImageIndex, 0), SingleImagePackModel.ShortCode)
|
|
roomid: displayName
|
|
Layout.preferredHeight: 130
|
|
Layout.preferredWidth: 130
|
|
crop: false
|
|
Layout.alignment: Qt.AlignHCenter
|
|
}
|
|
|
|
MatrixTextField {
|
|
Layout.fillWidth: true
|
|
Layout.columnSpan: 2
|
|
label: qsTr("Shortcode")
|
|
property int bindingCounter: 0
|
|
text: bindingCounter, imagePack.data(imagePack.index(currentImageIndex, 0), SingleImagePackModel.ShortCode)
|
|
onTextEdited: {
|
|
imagePack.setData(imagePack.index(currentImageIndex, 0), text, SingleImagePackModel.ShortCode);
|
|
// force text field to update in case the model disagreed with the new value.
|
|
bindingCounter++;
|
|
}
|
|
}
|
|
|
|
MatrixTextField {
|
|
id: bodyField
|
|
|
|
Layout.fillWidth: true
|
|
Layout.columnSpan: 2
|
|
label: qsTr("Body")
|
|
text: imagePack.data(imagePack.index(currentImageIndex, 0), SingleImagePackModel.Body)
|
|
onTextEdited: imagePack.setData(imagePack.index(currentImageIndex, 0), text, SingleImagePackModel.Body)
|
|
}
|
|
|
|
MatrixText {
|
|
Layout.margins: bodyField.textPadding
|
|
font.weight: Font.DemiBold
|
|
font.letterSpacing: font.pixelSize * 0.02
|
|
text: qsTr("Use as Emoji")
|
|
}
|
|
|
|
ToggleButton {
|
|
checked: imagePack.data(imagePack.index(currentImageIndex, 0), SingleImagePackModel.IsEmote)
|
|
onCheckedChanged: imagePack.setData(imagePack.index(currentImageIndex, 0), checked, SingleImagePackModel.IsEmote)
|
|
Layout.alignment: Qt.AlignRight
|
|
}
|
|
|
|
MatrixText {
|
|
Layout.margins: bodyField.textPadding
|
|
font.weight: Font.DemiBold
|
|
font.letterSpacing: font.pixelSize * 0.02
|
|
text: qsTr("Use as Sticker")
|
|
}
|
|
|
|
ToggleButton {
|
|
checked: imagePack.data(imagePack.index(currentImageIndex, 0), SingleImagePackModel.IsSticker)
|
|
onCheckedChanged: imagePack.setData(imagePack.index(currentImageIndex, 0), checked, SingleImagePackModel.IsSticker)
|
|
Layout.alignment: Qt.AlignRight
|
|
}
|
|
|
|
MatrixText {
|
|
Layout.margins: bodyField.textPadding
|
|
font.weight: Font.DemiBold
|
|
font.letterSpacing: font.pixelSize * 0.02
|
|
text: qsTr("Remove from pack")
|
|
}
|
|
|
|
Button {
|
|
text: qsTr("Remove")
|
|
onClicked: {
|
|
let temp = currentImageIndex;
|
|
currentImageIndex = -1;
|
|
imagePack.remove(temp);
|
|
}
|
|
Layout.alignment: Qt.AlignRight
|
|
}
|
|
|
|
Item {
|
|
Layout.columnSpan: 2
|
|
Layout.fillHeight: true
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
footer: DialogButtonBox {
|
|
id: buttons
|
|
|
|
standardButtons: DialogButtonBox.Save | DialogButtonBox.Cancel
|
|
onAccepted: {
|
|
imagePack.save();
|
|
win.close();
|
|
}
|
|
onRejected: win.close()
|
|
}
|
|
|
|
}
|