Files
komplex-hub/KomplexHubModule/Controls/SearchResultItem.qml
T
2026-06-25 03:09:00 -04:00

333 lines
7.9 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import KomplexHub
Item {
property string author: ""
property string description: ""
property string title: ""
property string thumbnail: ""
property string uuid: ""
property bool selected: false
property bool pexels: false
signal triggered
signal viewMoreTriggered
id: searchResultItemRoot
width: 256
height: 256
clip: true
Rectangle
{
id: searchResultItemContainer
anchors.fill: parent
border.color: palette.alternateBase.lighter(1.75)
color: palette.alternateBase.lighter(1.25)
MouseArea
{
property string lastState
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onEntered: () => {
states.hovered = true
}
onExited: () => {
if(!viewMoreButton.hovered)
states.hovered = false
}
onReleased: () => {
if(!states.selected)
{
searchResultItemRoot.triggered()
}
}
}
ColumnLayout
{
anchors.fill: parent
Rectangle
{
Layout.preferredWidth: 250
Layout.preferredHeight: 141
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
Layout.topMargin: 3
border.color: palette.alternateBase.lighter(1.75)
color: palette.base.lighter(1.25)
Image
{
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
id: thumnailImage
source: searchResultItemRoot.thumbnail
}
Image
{
antialiasing: true
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: Constants.mediumMargin
width: 24
height: 24
transform: Image.PreserveAspectFit
opacity: 0.5
source: "qrc:/images/icons/pexels-icon-filled-256.svg"
visible: searchResultItemRoot.pexels
}
}
Text
{
color: palette.text
text: searchResultItemRoot.title
font.pixelSize: 16
font.bold: true
elide: Text.ElideRight
Layout.preferredWidth: 246
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
}
Item { Layout.fillHeight: true }
Text
{
color: palette.text
font.pixelSize: 12
text: "By: " + searchResultItemRoot.author
leftPadding: 12
Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
Layout.preferredWidth: 250
visible: !searchResultItemRoot.pexels
}
Text
{
id: descriptionText
clip: true
color: palette.text
font.pixelSize: 12
text: searchResultItemRoot.description
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
textFormat: Text.PlainText
elide: Text.ElideRight
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.maximumHeight: 32
Layout.preferredHeight: 32
Layout.preferredWidth: 236
Layout.maximumWidth: 236
Layout.bottomMargin: 3
}
SquareButton
{
id: viewMoreButton
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.maximumHeight: 50
Layout.preferredHeight: 32
Layout.preferredWidth: 236
Layout.maximumWidth: 236
Layout.bottomMargin: 3
text: qsTr("View More")
opacity: 0
onTriggered: () => {
searchResultItemRoot.viewMoreTriggered()
}
}
Item { Layout.fillHeight: true }
}
}
QtObject
{
id: states
property bool clicked: false
property bool hovered: false
property alias selected: searchResultItemRoot.selected
property bool idle: true
onIdleChanged: () =>
{
if(idle)
{
clicked = false
hovered = false
selected = false
}
}
}
states: [
State {
name: "hovered"
when: states.hovered && !states.selected
PropertyChanges {
target: searchResultItemContainer
color: palette.alternateBase.lighter(1.5)
border.color: Qt.hsva(palette.accent.hslHue,
palette.accent.hslSaturation,
0.5, // Set custom lightness
1.0)
}
PropertyChanges
{
target: viewMoreButton
opacity: 0
Layout.preferredHeight: 0
}
PropertyChanges
{
target: descriptionText
opacity: 1
Layout.preferredHeight: 32
}
},
State {
name: "selected"
when: states.selected && !states.hovered
PropertyChanges
{
target: searchResultItemContainer
color: palette.accent
}
},
State
{
name: "view_more"
when: states.selected && states.hovered
PropertyChanges
{
target: viewMoreButton
opacity: 1
Layout.preferredHeight: 32
}
PropertyChanges
{
target: descriptionText
opacity: 0
Layout.preferredHeight: 0
}
},
State
{
name: "default"
when: states.idle
PropertyChanges
{
target: viewMoreButton
opacity: 0
Layout.preferredHeight: 0
}
PropertyChanges
{
target: descriptionText
opacity: 1
Layout.preferredHeight: 32
}
}
]
transitions:
[
Transition
{
to: "selected"
ColorAnimation
{
target: searchResultItemContainer
duration: 250
}
},
Transition
{
from: "selected"
to: "view_more"
NumberAnimation
{
target: viewMoreButton
property: "opacity"
duration: 250
easing.type: Easing.InOutQuad
}
},
Transition
{
from: "view_more"
to: "selected"
NumberAnimation
{
target: descriptionText
property: "opacity"
duration: 250
easing.type: Easing.InOutQuad
}
},
Transition
{
to: "default"
ColorAnimation
{
target: searchResultItemContainer
duration: 250
}
},
Transition
{
to: "hovered"
ColorAnimation
{
target: searchResultItemContainer
duration: 250
}
}
]
}