Kirigami-addons

FormGridContainer.qml
1// SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
2// SPDX-FileCopyrightText: 2023 Rishi Kumar <rsi.dev17@gmail.com>
3// SPDX-FileCopyrightText: 2023 Carl Schwan <carl@carlschwan.eu>
4// SPDX-License-Identifier: LGPL-2.0-or-later
5
6import QtQml
7import QtQuick
8import QtQuick.Controls as QQC2
9import QtQuick.Templates as T
10import QtQuick.Layouts
11
12import org.kde.kirigami as Kirigami
13
14import "private" as Private
15
16/**
17 * This component render a grid of small cards.
18 *
19 * This is used to display multiple information in a FormCard.FormLayout
20 * without taking too much vertical space.
21 *
22 * @code{.qml}
23 * import org.kde.kirigamiaddons.formcard as FormCard
24 *
25 * FormCard.FormGridContainer {
26 * id: container
27 *
28 * Layout.topMargin: Kirigami.Units.largeSpacing
29 * Layout.fillWidth: true
30 *
31 * infoCards: [
32 * FormCard.FormGridContainer.InfoCard {
33 * title: "42"
34 * subtitle: i18nc("@info:Number of Posts", "Posts")
35 * },
36 * FormCard.FormGridContainer.InfoCard {
37 * title: "42"
38 * subtitle: i18nc("@info:Number of followers.", "Followers")
39 * }
40 * ]
41 * }
42 * @endcode
43 *
44 *
45 * @since KirigamiAddons 0.11.0
46 *
47 * @inherit QtQuick.Item
48 */
49Item {
50 id: root
51
52 /**
53 * This property holds the maximum width of the grid.
54 */
55 property real maximumWidth: Kirigami.Units.gridUnit * 30
56
57 /**
58 * @brief This property holds the padding used around the content edges.
59 *
60 * default: `0`
61 */
62 property real padding: 0
63 property real verticalPadding: padding
64 property real horizontalPadding: padding
65 property real topPadding: verticalPadding
66 property real bottomPadding: verticalPadding
67 property real leftPadding: horizontalPadding
68 property real rightPadding: horizontalPadding
69
70 /**
71 * This property holds whether the card's width is being restricted.
72 */
73 readonly property bool cardWidthRestricted: root.width > root.maximumWidth
74
75 /**
76 * This property holds the InfoCards which should be displayed.
77 *
78 * Each InfoCard contains a title and an optional subtitle
79 *
80 * @code{.qml}
81 * import org.kde.kirigamiaddons.formcard as FormCard
82 *
83 * FormCard.FormGridContainer {
84 * infoCards: [
85 * FormCard.FormGridContainer.InfoCard {
86 * title: "42"
87 * subtitle: i18nc("@info:Number of Posts", "Posts")
88 * },
89 * FormCard.FormGridContainer.InfoCard {
90 * title: "42"
91 * },
92 * FormCard.FormGridContainer.InfoCard {
93 * title: "Details"
94 * action: Kirigami.Action {
95 * onClicked: pageStack.push("Details.qml")
96 * }
97 * }
98 * ]
99 * }
100 * @endcode
101 */
102 property list<QtObject> infoCards
103
104 component InfoCard: QtObject {
105 property bool visible: true
106 property string title
107 property string subtitle
108 property string buttonIcon
109 property string tooltipText
110 property int subtitleTextFormat: Text.AutoText
111 property Kirigami.Action action
112 }
113
114 Kirigami.Theme.colorSet: Kirigami.Theme.View
115 Kirigami.Theme.inherit: false
116
117 Layout.fillWidth: true
118
119 implicitHeight: topPadding + bottomPadding + grid.implicitHeight
120
121 Item {
122 id: _private
123
124 function getDarkness(background: color): real {
125 // Thanks to Gojir4 from the Qt forum
126 // https://forum.qt.io/topic/106362/best-way-to-set-text-color-for-maximum-contrast-on-background-color/
127 var temp = Qt.darker(background, 1);
128 var a = 1 - ( 0.299 * temp.r + 0.587 * temp.g + 0.114 * temp.b);
129 return a;
130 }
131
132 readonly property bool isDarkColor: {
133 const temp = Qt.darker(Kirigami.Theme.backgroundColor, 1);
134 return temp.a > 0 && getDarkness(Kirigami.Theme.backgroundColor) >= 0.4;
135 }
136
137 anchors {
138 top: parent.top
139 bottom: parent.bottom
140 left: parent.left
141 right: parent.right
142
143 leftMargin: root.cardWidthRestricted ? Math.round((root.width - root.maximumWidth) / 2) : 0
144 rightMargin: root.cardWidthRestricted ? Math.round((root.width - root.maximumWidth) / 2) : 0
145 }
146
147 GridLayout {
148 id: grid
149
150 readonly property int cellWidth: Kirigami.Units.gridUnit * 10
151 readonly property int visibleChildrenCount: visibleChildren.length - 1
152
153 anchors {
154 fill: parent
155 leftMargin: root.leftPadding
156 rightMargin: root.rightPadding
157 topMargin: root.topPadding
158 bottomMargin: root.bottomPadding
159 }
160
161 columns: root.cardWidthRestricted && grid.visibleChildrenCount % 3 === 0 ? 3 : 2
162 columnSpacing: Kirigami.Units.smallSpacing
163 rowSpacing: Kirigami.Units.smallSpacing
164
165 Repeater {
166 id: cardRepeater
167
168 model: root.infoCards
169
170 QQC2.AbstractButton {
171 id: infoCardDelegate
172
173 required property int index
174 required property QtObject modelData
175
176 readonly property string title: modelData.title
177 readonly property string subtitle: modelData.subtitle
178 readonly property string buttonIcon: modelData.buttonIcon
179 readonly property string tooltipText: modelData.tooltipText
180 readonly property int subtitleTextFormat: modelData.subtitleTextFormat
181
182 visible: modelData.visible
183
184 action: modelData.action
185
186 leftPadding: Kirigami.Units.largeSpacing
187 rightPadding: Kirigami.Units.largeSpacing
188 topPadding: Kirigami.Units.largeSpacing
189 bottomPadding: Kirigami.Units.largeSpacing
190
191 leftInset: root.cardWidthRestricted ? 0 : -infoCardDelegate.background.border.width
192 rightInset: root.cardWidthRestricted ? 0 : -infoCardDelegate.background.border.width
193
194 hoverEnabled: true
195
196 Accessible.name: title + " " + subtitle
197 Accessible.role: action ? Accessible.Button : Accessible.Note
198
199 Layout.preferredWidth: grid.cellWidth
200 Layout.columnSpan: grid.visibleChildrenCount % grid.columns !== 0 && index === grid.visibleChildrenCount - 1 ? 2 : 1
201 Layout.fillWidth: true
202 Layout.fillHeight: true
203
204 QQC2.ToolTip.text: tooltipText
205 QQC2.ToolTip.visible: tooltipText && hovered
206 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
207
208 background: Kirigami.ShadowedRectangle {
209 radius: root.cardWidthRestricted ? Kirigami.Units.cornerRadius : 0
210 color: Kirigami.Theme.backgroundColor
211
212 border {
213 color: _private.isDarkColor ? Qt.darker(Kirigami.Theme.backgroundColor, 1.2) : Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.15)
214 width: 1
215 }
216
217 shadow {
218 size: _private.isDarkColor ? Kirigami.Units.smallSpacing : Kirigami.Units.largeSpacing
219 color: Qt.alpha(Kirigami.Theme.textColor, 0.10)
220 }
221
222 Rectangle {
223 anchors.fill: parent
224 radius: root.cardWidthRestricted ? Kirigami.Units.cornerRadius : 0
225
226 color: {
227 let alpha = 0;
228
229 if (!infoCardDelegate.enabled || !infoCardDelegate.action) {
230 alpha = 0;
231 } else if (infoCardDelegate.pressed) {
232 alpha = 0.2;
233 } else if (infoCardDelegate.visualFocus) {
234 alpha = 0.1;
235 } else if (!Kirigami.Settings.tabletMode && infoCardDelegate.hovered) {
236 alpha = 0.07;
237 }
238
239 return Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, alpha)
240 }
241
242 Behavior on color {
243 ColorAnimation { duration: Kirigami.Units.shortDuration }
244 }
245 }
246 }
247
248 contentItem: RowLayout {
249 Kirigami.Icon {
250 id: icon
251
252 source: infoCardDelegate.buttonIcon
253 visible: source
254 Layout.alignment: Qt.AlignTop
255 }
256
257 ColumnLayout {
258 spacing: 0
259
260 // Title
261 Kirigami.Heading {
262 Layout.fillWidth: true
263 level: 4
264 text: infoCardDelegate.title
265 verticalAlignment: Text.AlignVCenter
266 horizontalAlignment: icon.visible ? Text.AlignLeft : Text.AlignHCenter
267 maximumLineCount: 2
268 elide: Text.ElideRight
269 wrapMode: Text.Wrap
270 }
271
272 // Subtitle
273 QQC2.Label {
274 Layout.fillWidth: true
275 Layout.fillHeight: true
276 visible: infoCardDelegate.subtitle
277 text: infoCardDelegate.subtitle
278 horizontalAlignment: icon.visible ? Text.AlignLeft : Text.AlignHCenter
279 elide: Text.ElideRight
280 wrapMode: Text.Wrap
281 textFormat: infoCardDelegate.subtitleTextFormat
282 opacity: 0.6
283 verticalAlignment: Text.AlignTop
284 onLinkActivated: (link) => modelData.linkActivated(link)
285 }
286 }
287 }
288 }
289 }
290 }
291 }
292}
KIOCORE_EXPORT CopyJob * link(const QList< QUrl > &src, const QUrl &destDir, JobFlags flags=DefaultFlags)
QStringView level(QStringView ifopt)
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:03:50 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.