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}
real maximumWidth
This property holds the maximum width of the grid.
list< QtObject > infoCards
This property holds the InfoCards which should be displayed.
real padding
This property holds the padding used around the content edges.
bool cardWidthRestricted
This property holds whether the card's width is being restricted.
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-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:49:11 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.