diff --git a/Mainpage.dox b/Mainpage.dox --- a/Mainpage.dox +++ b/Mainpage.dox @@ -37,6 +37,7 @@ - \link org::kde::kirigami::SwipeListItem SwipeListItem \endlink - \link org::kde::kirigami::Heading Heading \endlink - \link org::kde::kirigami::Label Label \endlink +- \link org::kde::kirigami::PlaceholderMessage PlaceholderMessage \endlink \section example Minimal Example diff --git a/kirigami.qrc b/kirigami.qrc --- a/kirigami.qrc +++ b/kirigami.qrc @@ -90,5 +90,6 @@ src/styles/org.kde.desktop/SwipeListItem.qml src/styles/org.kde.desktop/ApplicationWindow.qml src/styles/org.kde.desktop/AbstractApplicationHeader.qml + src/controls/PlaceholderMessage.qml diff --git a/kirigami.qrc.in b/kirigami.qrc.in --- a/kirigami.qrc.in +++ b/kirigami.qrc.in @@ -92,5 +92,6 @@ @kirigami_QML_DIR@/src/styles/org.kde.desktop/SwipeListItem.qml @kirigami_QML_DIR@/src/styles/org.kde.desktop/ApplicationWindow.qml @kirigami_QML_DIR@/src/styles/org.kde.desktop/AbstractApplicationHeader.qml + @kirigami_QML_DIR@/src/controls/PlaceholderMessage.qml diff --git a/src/controls/PlaceholderMessage.qml b/src/controls/PlaceholderMessage.qml new file mode 100644 --- /dev/null +++ b/src/controls/PlaceholderMessage.qml @@ -0,0 +1,167 @@ +/* + * SPDX-FileCopyrightText: 2020 by Nate Graham + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +import QtQuick 2.0 +import QtQuick.Controls 2.4 as QQC2 +import QtQuick.Layouts 1.13 +import org.kde.kirigami 2.12 as Kirigami + +import "private" + +/** + * A placeholder message indicating that a list view is empty. The message + * comprises a label with lightened text, an optional icon above the text, and + * an optional button below the text which can be used to easily show the user + * what to do next to add content to the view. + * + * Example usage: + * + * @code{.qml} + * import org.kde.kirigami 2.11 as Kirigami + ** used as a "this view is empty" message + * ListView { + * id: listView + * model: [...] + * delegate: [...] + * + * Kirigami.PlaceholderMessage { + * anchors.centerIn: parent + * anchors.left: parent.left + * anchors.right: parent.right + * + * visible: listView.count == 0 + * + * text: "There are no items in this list" + * } + * } + * @endcode + * @code{.qml} + ** Used as a "here's how to proceed" message + * ListView { + * id: listView + * model: [...] + * delegate: [...] + * + * Kirigami.PlaceholderMessage { + * anchors.centerIn: parent + * anchors.left: parent.left + * anchors.right: parent.right + * + * visible: listView.count == 0 + * + * text: "Add an item to proceed" + * + * action: Kirigami.Action { + * iconName: "list-add" + * text: "Add item..." + * onTriggered: { + * [...] + * } + * } + * } + * [...] + * } + * @endcode + * @code{.qml} + ** Used as a "there was a problem here" message + * Kirigami.Page { + * id: root + * readonly property bool networkConnected: [...] + * + * Kirigami.PlaceholderMessage { + * anchors.centerIn: parent + * anchors.left: parent.left + * anchors.right: parent.right + * + * visible: root.networkConnected + * + * icon: "network-disconnect" + * text: "Network disconnected; unable to load content" + * } + * } + * @endcode + * @since 2.12 + */ +ColumnLayout { + id: root + + /** + * text: string + * The text to show as a placeholder label + * + * Mandatory; no default value. + * + * @since 5.70 + */ + property alias text: label.text + + /** + * icon: QVariant + * The icon to show above the text label. Accepts "icon.name" and + * "icon.source" + * + * Optional; if undefined, the message will have no icon. + * Falls back to `undefined` if the specified icon is not valid or cannot + * be loaded. + * + * @since 5.70 + * @see Icon::source + */ + property ActionIconGroup icon: ActionIconGroup {} + + /** + * helperAction: QtQuickControls2 Action + * An action that helps the user proceed. Typically used to guide the user + * to the next step for adding content or items to an empty view. + * + * Optional; if undefined, no button will appear below the text label. + * + * @since 5.70 + */ + property alias helpfulAction: actionButton.action + + spacing: units.largeSpacing + + Kirigami.Icon { + + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: Kirigami.Units.iconSizes.huge + Layout.preferredHeight: Kirigami.Units.iconSizes.huge + + source: { + if (root.icon.source && root.icon.source.length > 0) { + return root.icon.source + } else if (root.icon.name && root.icon.name.length > 0) { + return root.icon.name + } + return undefined + } + + visible: source != undefined + opacity: 0.5 + } + + Kirigami.Heading { + id: label + + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + horizontalAlignment: Qt.AlignHCenter + + level: 2 + opacity: 0.5 + + wrapMode: Text.WordWrap + } + + QQC2.Button { + id: actionButton + + Layout.alignment: Qt.AlignHCenter + + visible: action && action.visible + } +} diff --git a/src/controls/plugins.qmltypes b/src/controls/plugins.qmltypes --- a/src/controls/plugins.qmltypes +++ b/src/controls/plugins.qmltypes @@ -549,6 +549,17 @@ Property { name: "containsMouse"; type: "bool"; isReadonly: true } Property { name: "_default"; type: "QQuickItem"; isPointer: true } } + Component { + prototype: "QQuickItem" + name: "org.kde.kirigami/PlaceholderMessage 2.12" + exports: ["org.kde.kirigami/PlaceholderMessage 2.12"] + exportMetaObjectRevisions: [0] + isComposite: true + defaultProperty: "data" + Property { name: "text"; type: "string" } + Property { name: "icon"; type: "string" } + Property { name: "fadedIcon"; type: "bool" } + } Component { prototype: "QQuickItem" name: "QtQuick.Controls.Material.impl/BoxShadow 2.0" diff --git a/src/kirigamiplugin.cpp b/src/kirigamiplugin.cpp --- a/src/kirigamiplugin.cpp +++ b/src/kirigamiplugin.cpp @@ -243,6 +243,7 @@ qmlRegisterType(uri, 2, 12, "ShadowedRectangle"); qmlRegisterType(uri, 2, 12, "ShadowedTexture"); qmlRegisterType(componentUrl(QStringLiteral("ShadowedImage.qml")), uri, 2, 12, "ShadowedImage"); + qmlRegisterType(componentUrl(QStringLiteral("PlaceholderMessage.qml")), uri, 2, 12, "PlaceholderMessage"); qmlRegisterUncreatableType(uri, 2, 12, "BorderGroup", QStringLiteral("Used as grouped property")); qmlRegisterUncreatableType(uri, 2, 12, "ShadowGroup", QStringLiteral("Used as grouped property")); diff --git a/src/qmldir b/src/qmldir --- a/src/qmldir +++ b/src/qmldir @@ -51,3 +51,4 @@ SearchField 2.8 SearchField.qml PasswordField 2.8 PasswordField.qml ListSectionHeader 2.10 ListSectionHeader.qml +PlaceholderMessage 2.12 PlaceholderMessage.qml