From bbd0e71fd680a29ddd89bebb99a8c32ac33b6088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Tinkl?= Date: Fri, 19 Apr 2024 10:39:50 +0200 Subject: [PATCH] chore(StoryBook): add Colors page - gives an overview of all the `Theme.palette.foo` colors - the color name/code can be copied to clipboard - light/dark variant supported via storybook's "Dark mode" switch - integrated search (both the color name and value) --- storybook/pages/ColorsPage.qml | 278 +++++++++++++++++++ ui/StatusQ/include/StatusQ/QClipboardProxy.h | 1 + ui/StatusQ/src/QClipboardProxy.cpp | 7 +- 3 files changed, 285 insertions(+), 1 deletion(-) create mode 100644 storybook/pages/ColorsPage.qml diff --git a/storybook/pages/ColorsPage.qml b/storybook/pages/ColorsPage.qml new file mode 100644 index 0000000000..85d2bffef7 --- /dev/null +++ b/storybook/pages/ColorsPage.qml @@ -0,0 +1,278 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import StatusQ 0.1 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 + +import Storybook 1.0 + +import SortFilterProxyModel 0.2 + +SplitView { + id: root + + orientation: Qt.Vertical + + component ColorRectangle: Rectangle { + id: colorRectangle + property alias text: textLabel.text + + implicitWidth: 120 + implicitHeight: 60 + Column { + anchors.centerIn: parent + Row { + spacing: 4 + anchors.horizontalCenter: parent.horizontalCenter + Text { + id: textLabel + } + ToolButton { + focusPolicy: Qt.NoFocus + anchors.verticalCenter: parent.verticalCenter + width: 16 + height: 16 + padding: 0 + text: "📋" + font.pixelSize: 10 + onClicked: QClipboardProxy.copyTextToClipboard(textLabel.text) + ToolTip.text: "Copy color name" + ToolTip.visible: hovered + } + } + Row { + spacing: 4 + anchors.horizontalCenter: parent.horizontalCenter + Text { + id: colorLabel + color: textLabel.color + text: colorRectangle.color.toString() + } + ToolButton { + focusPolicy: Qt.NoFocus + anchors.verticalCenter: parent.verticalCenter + width: 16 + height: 16 + padding: 0 + text: "📋" + font.pixelSize: 10 + onClicked: QClipboardProxy.copyTextToClipboard(colorLabel.text) + ToolTip.text: "Copy color value" + ToolTip.visible: hovered + } + } + } + } + + component ColorFlow: ColumnLayout { + id: colorFlow + + property string title + property var model + + ListModel { + id: listModel + Component.onCompleted: { + append(Object.entries(colorFlow.model)) + } + } + + Label { + Layout.topMargin: 8 + //visible: colorRepeater.count + font.weight: Font.Medium + text: "%1 (%2)".arg(colorFlow.title).arg(colorRepeater.count) + } + Flow { + Layout.preferredWidth: scrollview.availableWidth + spacing: 5 + + Repeater { + id: colorRepeater + model: SortFilterProxyModel { + sourceModel: listModel + proxyRoles: [ + ExpressionRole { + name: "name" + expression: model[0] + }, + ExpressionRole { + name: "color" + expression: model[1] + } + ] + filters: FastExpressionFilter { + expression: { + searchField.searchText + return (!!model.name && model.name.toLowerCase().includes(searchField.searchText)) || + (!!model.color && model.color.toLowerCase().includes(searchField.searchText)) + } + enabled: searchField.searchText !== "" + expectedRoles: ["name", "color"] + } + } + delegate: ColorRectangle { + text: model.name + color: model.color + } + } + } + } + + Component.onCompleted: searchField.forceActiveFocus() + + ScrollView { + id: scrollview + contentWidth: availableWidth + SplitView.fillHeight: true + padding: 8 + + ColumnLayout { + spacing: 0 + RowLayout { + Label { + text: "Search" + font.weight: Font.Medium + } + TextField { + readonly property string searchText: text.toLowerCase() + id: searchField + } + ToolButton { + focusPolicy: Qt.NoFocus + text: "❌" + enabled: searchField.searchText !== "" + onClicked: searchField.clear() + } + } + + ColorFlow { + title: "Base" + model: { + "baseColor1": Theme.palette.baseColor1.toString(), + "baseColor2": Theme.palette.baseColor2.toString(), + "baseColor3": Theme.palette.baseColor3.toString(), + "baseColor4": Theme.palette.baseColor4.toString(), + "baseColor5": Theme.palette.baseColor5.toString() + } + } + + ColorFlow { + title: "Primary" + model: { + "primaryColor1": Theme.palette.primaryColor1.toString(), + "primaryColor2": Theme.palette.primaryColor2.toString(), + "primaryColor3": Theme.palette.primaryColor3.toString() + } + } + + ColorFlow { + title: "Danger" + model: { + "dangerColor1": Theme.palette.dangerColor1.toString(), + "dangerColor2": Theme.palette.dangerColor2.toString(), + "dangerColor3": Theme.palette.dangerColor3.toString() + } + } + + ColorFlow { + title: "Warning" + model: { + "warningColor1": Theme.palette.warningColor1.toString(), + "warningColor2": Theme.palette.warningColor2.toString(), + "warningColor3": Theme.palette.warningColor3.toString() + } + } + + ColorFlow { + title: "Success" + model: { + "successColor1": Theme.palette.successColor1.toString(), + "successColor2": Theme.palette.successColor2.toString(), + "successColor3": Theme.palette.successColor3.toString() + } + } + + ColorFlow { + title: "Direct" + model: { + "directColor1": Theme.palette.directColor1.toString(), + "directColor2": Theme.palette.directColor2.toString(), + "directColor3": Theme.palette.directColor3.toString(), + "directColor4": Theme.palette.directColor4.toString(), + "directColor5": Theme.palette.directColor5.toString(), + "directColor6": Theme.palette.directColor6.toString(), + "directColor7": Theme.palette.directColor7.toString(), + "directColor8": Theme.palette.directColor8.toString(), + "directColor9": Theme.palette.directColor9.toString() + } + } + + ColorFlow { + title: "Indirect" + model: { + "indirectColor1": Theme.palette.indirectColor1.toString(), + "indirectColor2": Theme.palette.indirectColor2.toString(), + "indirectColor3": Theme.palette.indirectColor3.toString(), + "indirectColor4": Theme.palette.indirectColor4.toString() + } + } + + ColorFlow { + title: "Mention" + model: { + "mentionColor1": Theme.palette.mentionColor1.toString(), + "mentionColor2": Theme.palette.mentionColor2.toString(), + "mentionColor3": Theme.palette.mentionColor3.toString(), + "mentionColor4": Theme.palette.mentionColor4.toString() + } + } + + ColorFlow { + title: "Pin" + model: { + "pinColor1": Theme.palette.pinColor1.toString(), + "pinColor2": Theme.palette.pinColor2.toString(), + "pinColor3": Theme.palette.pinColor3.toString() + } + } + + ColorFlow { + title: "Misc" + model: { + "miscColor1": Theme.palette.miscColor1.toString(), + "miscColor2": Theme.palette.miscColor2.toString(), + "miscColor3": Theme.palette.miscColor3.toString(), + "miscColor4": Theme.palette.miscColor4.toString(), + "miscColor5": Theme.palette.miscColor5.toString(), + "miscColor6": Theme.palette.miscColor6.toString(), + "miscColor7": Theme.palette.miscColor7.toString(), + "miscColor8": Theme.palette.miscColor8.toString(), + "miscColor9": Theme.palette.miscColor9.toString(), + "miscColor10": Theme.palette.miscColor10.toString(), + "miscColor11": Theme.palette.miscColor11.toString(), + "miscColor12": Theme.palette.miscColor12.toString() + } + } + + ColorFlow { + title: "User customization" + model: Theme.palette.userCustomizationColors + } + + ColorFlow { + title: "Identicon ring colors" + model: Theme.palette.identiconRingColors + } + + ColorFlow { + title: "Status colors" + model: StatusColors.colors + } + } + } +} + +// category: Core diff --git a/ui/StatusQ/include/StatusQ/QClipboardProxy.h b/ui/StatusQ/include/StatusQ/QClipboardProxy.h index c24926bcdb..cb530308b8 100644 --- a/ui/StatusQ/include/StatusQ/QClipboardProxy.h +++ b/ui/StatusQ/include/StatusQ/QClipboardProxy.h @@ -54,6 +54,7 @@ public: Q_INVOKABLE bool isValidImageUrl(const QUrl &url, const QStringList &acceptedExtensions) const; Q_INVOKABLE qint64 getFileSize(const QUrl &url) const; + Q_INVOKABLE void copyTextToClipboard(const QString& text); signals: void contentChanged(); diff --git a/ui/StatusQ/src/QClipboardProxy.cpp b/ui/StatusQ/src/QClipboardProxy.cpp index 00322082ad..fa4212b572 100644 --- a/ui/StatusQ/src/QClipboardProxy.cpp +++ b/ui/StatusQ/src/QClipboardProxy.cpp @@ -59,7 +59,7 @@ QString QClipboardProxy::imageBase64() const QByteArray byteArray; QBuffer buffer(&byteArray); img.save(&buffer, "JPG"); - return QStringLiteral("data:image/jpeg;base64,") + byteArray.toBase64(); + return QByteArrayLiteral("data:image/jpeg;base64,") + byteArray.toBase64(); } bool QClipboardProxy::hasUrls() const @@ -87,3 +87,8 @@ qint64 QClipboardProxy::getFileSize(const QUrl& url) const } return 0; } + +void QClipboardProxy::copyTextToClipboard(const QString &text) +{ + m_clipboard->setText(text); +}