From 13d7f9b3225b8a05195b2a868b3edf6056dc482d Mon Sep 17 00:00:00 2001 From: James Graham Date: Sat, 7 Feb 2026 17:18:26 +0000 Subject: [PATCH] Make sure that the style menu shows the right style name for code and quote. Also when in quote mode the valid styles are now transformed to how they look in quote to show they are valid. Clicking quote style again in a quote block will return to paragrpah style from heading now --- src/chatbar/RichEditBar.qml | 6 ++- src/chatbar/StyleButton.qml | 3 ++ src/chatbar/StyleDelegate.qml | 5 ++- src/chatbar/StylePicker.qml | 6 +++ src/chatbar/chatbuttonhelper.cpp | 27 +++++++++++++- src/chatbar/chatbuttonhelper.h | 10 +++++ src/chatbar/styledelegatehelper.cpp | 19 +++++++++- src/chatbar/styledelegatehelper.h | 11 ++++++ src/libneochat/enums/richformat.cpp | 37 +++++++++++++------ src/libneochat/enums/richformat.h | 2 +- .../models/chatbarmessagecontentmodel.cpp | 2 +- 11 files changed, 110 insertions(+), 18 deletions(-) diff --git a/src/chatbar/RichEditBar.qml b/src/chatbar/RichEditBar.qml index fec932c04..938f75f94 100644 --- a/src/chatbar/RichEditBar.qml +++ b/src/chatbar/RichEditBar.qml @@ -57,6 +57,7 @@ RowLayout { readonly property ChatButtonHelper chatButtonHelper: ChatButtonHelper { textItem: root.contentModel.focusedTextItem + inQuote: root.contentModel.focusType == LibNeoChat.MessageComponentType.Quote } signal clicked @@ -195,11 +196,12 @@ RowLayout { } StyleButton { id: styleButton - Layout.minimumWidth: compressed ? -1 : Kirigami.Units.gridUnit * 8 + Kirigami.Units.largeSpacing * 2 + Layout.minimumWidth: compressed ? -1 : Kirigami.Units.gridUnit * 10 + Kirigami.Units.largeSpacing * 2 icon.name: "typewriter" text: i18nc("@action:button", "Text Style") style: root.chatButtonHelper.currentStyle + inQuote: root.contentModel.focusType == LibNeoChat.MessageComponentType.Quote compressed: root.maxAvailableWidth < root.extraTextCompressedImplicitWidth enabled: root.chatButtonHelper.styleFormatEnabled display: QQC2.AbstractButton.IconOnly @@ -216,8 +218,10 @@ RowLayout { StylePicker { id: styleMenu + width: styleButton.compressed ? implicitWidth : styleButton.width chatContentModel: root.contentModel chatButtonHelper: root.chatButtonHelper + inQuote: root.contentModel.focusType == LibNeoChat.MessageComponentType.Quote onClosed: { root.clicked() diff --git a/src/chatbar/StyleButton.qml b/src/chatbar/StyleButton.qml index 517838b95..6a22f6ef5 100644 --- a/src/chatbar/StyleButton.qml +++ b/src/chatbar/StyleButton.qml @@ -16,6 +16,8 @@ QQC2.AbstractButton { required property int style + required property bool inQuote + property bool open: false property bool compressed: false @@ -37,6 +39,7 @@ QQC2.AbstractButton { visible: !root.compressed style: root.style + inQuote: root.inQuote sizeText: false onPressed: root.clicked() diff --git a/src/chatbar/StyleDelegate.qml b/src/chatbar/StyleDelegate.qml index 3635176fd..31e123f02 100644 --- a/src/chatbar/StyleDelegate.qml +++ b/src/chatbar/StyleDelegate.qml @@ -16,6 +16,8 @@ QQC2.TextArea { required property int style + required property bool inQuote + property bool highlight: false property bool sizeText: true @@ -52,11 +54,12 @@ QQC2.TextArea { StyleDelegateHelper { textItem: root + inQuote: root.inQuote } background: Rectangle { color: Kirigami.Theme.backgroundColor - Kirigami.Theme.colorSet: root.style === LibNeoChat.RichFormat.Quote ? Kirigami.Theme.Window : Kirigami.Theme.View + Kirigami.Theme.colorSet: root.style === LibNeoChat.RichFormat.Quote || (root.inQuote && !(root.style == LibNeoChat.RichFormat.Paragraph || root.style == LibNeoChat.RichFormat.Code)) ? Kirigami.Theme.Window : Kirigami.Theme.View Kirigami.Theme.inherit: false radius: Kirigami.Units.cornerRadius border { diff --git a/src/chatbar/StylePicker.qml b/src/chatbar/StylePicker.qml index 5285a665c..7f1164bc9 100644 --- a/src/chatbar/StylePicker.qml +++ b/src/chatbar/StylePicker.qml @@ -17,6 +17,7 @@ QQC2.Popup { required property MessageContent.ChatBarMessageContentModel chatContentModel required property ChatButtonHelper chatButtonHelper + required property bool inQuote y: -implicitHeight padding: Kirigami.Units.largeSpacing @@ -35,7 +36,12 @@ QQC2.Popup { Layout.minimumWidth: Kirigami.Units.gridUnit * 8 Layout.minimumHeight: Kirigami.Units.gridUnit * 2 + enabled: chatButtonHelper.richFormatEnabled || + index == LibNeoChat.RichFormat.Paragraph || + index == LibNeoChat.RichFormat.Code || + index == LibNeoChat.RichFormat.Quote style: index + inQuote: root.inQuote highlight: root.chatButtonHelper.currentStyle === index || hovered onPressed: (event) => { diff --git a/src/chatbar/chatbuttonhelper.cpp b/src/chatbar/chatbuttonhelper.cpp index e2035bb8e..5d3cc265a 100644 --- a/src/chatbar/chatbuttonhelper.cpp +++ b/src/chatbar/chatbuttonhelper.cpp @@ -41,6 +41,7 @@ void ChatButtonHelper::setTextItem(ChatTextItemHelper *textItem) } }); connect(m_textItem, &ChatTextItemHelper::textFormatChanged, this, &ChatButtonHelper::richFormatEnabledChanged); + connect(m_textItem, &ChatTextItemHelper::textFormatChanged, this, &ChatButtonHelper::styleChanged); connect(m_textItem, &ChatTextItemHelper::charFormatChanged, this, &ChatButtonHelper::charFormatChanged); connect(m_textItem, &ChatTextItemHelper::styleChanged, this, &ChatButtonHelper::styleChanged); connect(m_textItem, &ChatTextItemHelper::listChanged, this, &ChatButtonHelper::listChanged); @@ -48,6 +49,23 @@ void ChatButtonHelper::setTextItem(ChatTextItemHelper *textItem) Q_EMIT textItemChanged(); Q_EMIT richFormatEnabledChanged(); + Q_EMIT styleChanged(); +} + +bool ChatButtonHelper::inQuote() const +{ + return m_inQuote; +} + +void ChatButtonHelper::setInQuote(bool inQuote) +{ + if (inQuote == m_inQuote) { + return; + } + m_inQuote = inQuote; + Q_EMIT inQuoteChanged(); + Q_EMIT richFormatEnabledChanged(); + Q_EMIT styleChanged(); } bool ChatButtonHelper::richFormatEnabled() const @@ -158,7 +176,14 @@ RichFormat::Format ChatButtonHelper::currentStyle() const if (!m_textItem) { return RichFormat::Paragraph; } - return static_cast(m_textItem->textCursor().blockFormat().headingLevel()); + if (!richFormatEnabled()) { + return RichFormat::Code; + } + const auto currentHeadingLevel = m_textItem->textCursor().blockFormat().headingLevel(); + if (currentHeadingLevel == 0 && m_inQuote) { + return RichFormat::Quote; + } + return static_cast(currentHeadingLevel); } void ChatButtonHelper::setFormat(RichFormat::Format format) diff --git a/src/chatbar/chatbuttonhelper.h b/src/chatbar/chatbuttonhelper.h index 8231b50bf..aeace0b50 100644 --- a/src/chatbar/chatbuttonhelper.h +++ b/src/chatbar/chatbuttonhelper.h @@ -23,6 +23,11 @@ class ChatButtonHelper : public QObject */ Q_PROPERTY(ChatTextItemHelper *textItem READ textItem WRITE setTextItem NOTIFY textItemChanged) + /** + * @brief Whether the current block is a Quote block. + */ + Q_PROPERTY(bool inQuote READ inQuote WRITE setInQuote NOTIFY inQuoteChanged) + /** * @brief Whether rich formating is enabled at the current cursor location. */ @@ -94,6 +99,9 @@ public: ChatTextItemHelper *textItem() const; void setTextItem(ChatTextItemHelper *textItem); + bool inQuote() const; + void setInQuote(bool inQuote); + bool richFormatEnabled() const; bool styleFormatEnabled() const; bool bold() const; @@ -140,6 +148,7 @@ public: Q_SIGNALS: void textItemChanged(); + void inQuoteChanged(); void richFormatEnabledChanged(); void charFormatChanged(); void styleChanged(); @@ -147,6 +156,7 @@ Q_SIGNALS: private: QPointer m_textItem; + bool m_inQuote = false; void selectLinkText(QTextCursor &cursor) const; }; diff --git a/src/chatbar/styledelegatehelper.cpp b/src/chatbar/styledelegatehelper.cpp index c6dd06e98..8338e2521 100644 --- a/src/chatbar/styledelegatehelper.cpp +++ b/src/chatbar/styledelegatehelper.cpp @@ -47,6 +47,21 @@ QTextDocument *StyleDelegateHelper::document() const return quickDocument ? quickDocument->textDocument() : nullptr; } +bool StyleDelegateHelper::inQuote() const +{ + return m_inQuote; +} + +void StyleDelegateHelper::setInQuote(bool inQuote) +{ + if (inQuote == m_inQuote) { + return; + } + m_inQuote = inQuote; + formatDocument(); + Q_EMIT inQuoteChanged(); +} + void StyleDelegateHelper::formatDocument() { if (!document()) { @@ -62,7 +77,7 @@ void StyleDelegateHelper::formatDocument() cursor.select(QTextCursor::Document); cursor.removeSelectedText(); const auto style = static_cast(m_textItem->property("style").toInt()); - const auto string = RichFormat::styleString(style); + const auto string = RichFormat::styleString(style, m_inQuote); const auto sizeText = static_cast(m_textItem->property("sizeText").toBool()); const int headingLevel = style <= 6 && sizeText ? style : 0; @@ -83,7 +98,7 @@ void StyleDelegateHelper::formatDocument() chrfmt.setFontItalic(true); } - cursor.mergeBlockCharFormat(chrfmt); + cursor.setBlockCharFormat(chrfmt); cursor.insertText(string); cursor.endEditBlock(); } diff --git a/src/chatbar/styledelegatehelper.h b/src/chatbar/styledelegatehelper.h index 87b7f545a..15b41354b 100644 --- a/src/chatbar/styledelegatehelper.h +++ b/src/chatbar/styledelegatehelper.h @@ -19,19 +19,30 @@ class StyleDelegateHelper : public QObject */ Q_PROPERTY(QQuickItem *textItem READ textItem WRITE setTextItem NOTIFY textItemChanged) + /** + * @brief Whether the current block is a Quote block. + */ + Q_PROPERTY(bool inQuote READ inQuote WRITE setInQuote NOTIFY inQuoteChanged) + public: explicit StyleDelegateHelper(QObject *parent = nullptr); QQuickItem *textItem() const; void setTextItem(QQuickItem *textItem); + bool inQuote() const; + void setInQuote(bool inQuote); + Q_SIGNALS: void textItemChanged(); + void inQuoteChanged(); private: QPointer m_textItem; QTextDocument *document() const; + bool m_inQuote = false; + private Q_SLOTS: void formatDocument(); }; diff --git a/src/libneochat/enums/richformat.cpp b/src/libneochat/enums/richformat.cpp index f57ec1518..a30b09a6b 100644 --- a/src/libneochat/enums/richformat.cpp +++ b/src/libneochat/enums/richformat.cpp @@ -9,30 +9,45 @@ #include -QString RichFormat::styleString(Format format) +QString RichFormat::styleString(Format format, bool inQuoteBlock) { + QString formatString; switch (format) { case Paragraph: - return i18nc("As in the default paragraph text style in the chat bar", "Paragraph Style"); + formatString = i18nc("As in the default paragraph text style in the chat bar", "Paragraph Style"); + break; case Heading1: - return i18nc("As in heading level 1 text style in the chat bar", "Heading 1"); + formatString = i18nc("As in heading level 1 text style in the chat bar", "Heading 1"); + break; case Heading2: - return i18nc("As in heading level 2 text style in the chat bar", "Heading 2"); + formatString = i18nc("As in heading level 2 text style in the chat bar", "Heading 2"); + break; case Heading3: - return i18nc("As in heading level 3 text style in the chat bar", "Heading 3"); + formatString = i18nc("As in heading level 3 text style in the chat bar", "Heading 3"); + break; case Heading4: - return i18nc("As in heading level 4 text style in the chat bar", "Heading 4"); + formatString = i18nc("As in heading level 4 text style in the chat bar", "Heading 4"); + break; case Heading5: - return i18nc("As in heading level 5 text style in the chat bar", "Heading 5"); + formatString = i18nc("As in heading level 5 text style in the chat bar", "Heading 5"); + break; case Heading6: - return i18nc("As in heading level 6 text style in the chat bar", "Heading 6"); + formatString = i18nc("As in heading level 6 text style in the chat bar", "Heading 6"); + break; case Code: - return i18nc("As in code text style in the chat bar", "Code"); + formatString = i18nc("As in code text style in the chat bar", "Code"); + break; case Quote: - return i18nc("As in quote text style in the chat bar", "\"Quote\""); + if (inQuoteBlock) { + formatString = i18nc("As in the default paragraph text style inside a quote block in the chat bar", "Quote Paragraph Style"); + break; + } + formatString = i18nc("As in quote text style in the chat bar", "Quote"); + break; default: - return {}; + break; } + return u"%1%2%1"_s.arg(inQuoteBlock && !(format == Paragraph || format == Code) ? u"\""_s : u""_s, formatString); }; RichFormat::FormatType RichFormat::typeForFormat(Format format) diff --git a/src/libneochat/enums/richformat.h b/src/libneochat/enums/richformat.h index a13d621d8..271dfe784 100644 --- a/src/libneochat/enums/richformat.h +++ b/src/libneochat/enums/richformat.h @@ -67,7 +67,7 @@ public: * * @sa Format */ - static QString styleString(Format format); + static QString styleString(Format format, bool inQuoteBlock = false); /** * @brief Return the FormatType for the Format. diff --git a/src/messagecontent/models/chatbarmessagecontentmodel.cpp b/src/messagecontent/models/chatbarmessagecontentmodel.cpp index 93e2150f4..e901fc4d2 100644 --- a/src/messagecontent/models/chatbarmessagecontentmodel.cpp +++ b/src/messagecontent/models/chatbarmessagecontentmodel.cpp @@ -430,7 +430,7 @@ void ChatBarMessageContentModel::insertStyleAtCursor(RichFormat::Format style) void ChatBarMessageContentModel::insertComponentAtCursor(MessageComponentType::Type type) { if (m_components[m_currentFocusComponent.row()].type == type) { - if (type == MessageComponentType::Text && focusedTextItem()) { + if ((type == MessageComponentType::Text || type == MessageComponentType::Quote) && focusedTextItem()) { focusedTextItem()->mergeFormatOnCursor(RichFormat::Paragraph); } return;