Disallow formatting when there is an attachment and when adding one if there is rich formatting warn the user it will be removed and remove if they accept.

This commit is contained in:
James Graham
2026-01-10 16:27:46 +00:00
parent d64e6fc206
commit f4cb660422
7 changed files with 257 additions and 44 deletions

View File

@@ -73,7 +73,7 @@ QQC2.ToolBar {
onActivated: boldButton.clicked()
}
icon.name: "format-text-bold"
enabled: root.contentModel.focusType !== LibNeoChat.MessageComponentType.Code
enabled: chatButtonHelper.richFormatEnabled
text: i18nc("@action:button", "Bold")
display: QQC2.AbstractButton.IconOnly
checkable: true
@@ -94,7 +94,7 @@ QQC2.ToolBar {
onActivated: italicButton.clicked()
}
icon.name: "format-text-italic"
enabled: root.contentModel.focusType !== LibNeoChat.MessageComponentType.Code
enabled: chatButtonHelper.richFormatEnabled
text: i18nc("@action:button", "Italic")
display: QQC2.AbstractButton.IconOnly
checkable: true
@@ -115,7 +115,7 @@ QQC2.ToolBar {
onActivated: underlineButton.clicked()
}
icon.name: "format-text-underline"
enabled: root.contentModel.focusType !== LibNeoChat.MessageComponentType.Code
enabled: chatButtonHelper.richFormatEnabled
text: i18nc("@action:button", "Underline")
display: QQC2.AbstractButton.IconOnly
checkable: true
@@ -131,7 +131,7 @@ QQC2.ToolBar {
}
QQC2.ToolButton {
icon.name: "format-text-strikethrough"
enabled: root.contentModel.focusType !== LibNeoChat.MessageComponentType.Code
enabled: chatButtonHelper.richFormatEnabled
text: i18nc("@action:button", "Strikethrough")
display: QQC2.AbstractButton.IconOnly
checkable: true
@@ -150,7 +150,7 @@ QQC2.ToolBar {
id: compressedTextFormatButton
visible: root.maxAvailableWidth < root.listCompressedImplicitWidth
icon.name: "dialog-text-and-font"
enabled: root.contentModel.focusType !== LibNeoChat.MessageComponentType.Code
enabled: chatButtonHelper.richFormatEnabled
text: i18nc("@action:button", "Format Text")
display: QQC2.AbstractButton.IconOnly
checkable: true
@@ -218,7 +218,7 @@ QQC2.ToolBar {
visible: root.maxAvailableWidth > root.uncompressedImplicitWidth
QQC2.ToolButton {
icon.name: "format-list-unordered"
enabled: root.contentModel.focusType !== LibNeoChat.MessageComponentType.Code
enabled: chatButtonHelper.richFormatEnabled
text: i18nc("@action:button", "Unordered List")
display: QQC2.AbstractButton.IconOnly
checkable: true
@@ -234,7 +234,7 @@ QQC2.ToolBar {
}
QQC2.ToolButton {
icon.name: "format-list-ordered"
enabled: root.contentModel.focusType !== LibNeoChat.MessageComponentType.Code
enabled: chatButtonHelper.richFormatEnabled
text: i18nc("@action:button", "Ordered List")
display: QQC2.AbstractButton.IconOnly
checkable: true
@@ -251,7 +251,7 @@ QQC2.ToolBar {
QQC2.ToolButton {
id: indentAction
icon.name: "format-indent-more"
enabled: root.contentModel.focusType !== LibNeoChat.MessageComponentType.Code && root.chatButtonHelper.canIndentListMore
enabled: chatButtonHelper.richFormatEnabled && root.chatButtonHelper.canIndentListMore
text: i18nc("@action:button", "Increase List Level")
display: QQC2.AbstractButton.IconOnly
onClicked: {
@@ -266,7 +266,7 @@ QQC2.ToolBar {
QQC2.ToolButton {
id: dedentAction
icon.name: "format-indent-less"
enabled: root.contentModel.focusType !== LibNeoChat.MessageComponentType.Code && root.chatButtonHelper.canIndentListLess
enabled: chatButtonHelper.richFormatEnabled && root.chatButtonHelper.canIndentListLess
text: i18nc("@action:button", "Decrease List Level")
display: QQC2.AbstractButton.IconOnly
onClicked: {
@@ -281,7 +281,7 @@ QQC2.ToolBar {
}
QQC2.ToolButton {
id: compressedListButton
enabled: root.contentModel.focusType !== LibNeoChat.MessageComponentType.Code
enabled: chatButtonHelper.richFormatEnabled
visible: root.maxAvailableWidth < root.uncompressedImplicitWidth
icon.name: "format-list-unordered"
text: i18nc("@action:button", "List Style")
@@ -315,6 +315,7 @@ QQC2.ToolBar {
QQC2.MenuItem {
icon.name: "format-indent-more"
text: i18nc("@action:button", "Increase List Level")
enabled: root.chatButtonHelper.canIndentListMore
onTriggered: {
root.chatButtonHelper.indentListMore();
root.clicked();
@@ -323,6 +324,7 @@ QQC2.ToolBar {
QQC2.MenuItem {
icon.name: "format-indent-less"
text: i18nc("@action:button", "Decrease List Level")
enabled: root.chatButtonHelper.canIndentListLess
onTriggered: {
root.chatButtonHelper.indentListLess();
root.clicked();
@@ -338,6 +340,7 @@ QQC2.ToolBar {
id: styleButton
icon.name: "typewriter"
text: i18nc("@action:button", "Text Style")
enabled: root.chatButtonHelper.styleFormatEnabled
display: QQC2.AbstractButton.IconOnly
checkable: true
checked: styleMenu.visible
@@ -422,10 +425,29 @@ QQC2.ToolBar {
display: QQC2.AbstractButton.IconOnly
onClicked: {
if (!root.contentModel.hasRichFormatting) {
fileDialog();
return;
}
let warningDialog = Qt.createComponent('org.kde.kirigami', 'PromptDialog').createObject(QQC2.Overlay.overlay, {
dialogType: Kirigami.PromptDialog.Warning,
title: i18n("Attach an image or file?"),
subtitle: i18n("Attachments can only have plain text captions, all rich formatting will be removed"),
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
});
warningDialog.onAccepted.connect(() => {
attachmentButton.fileDialog();
});
warningDialog.open();
}
function fileDialog(): void {
let dialog = (LibNeoChat.Clipboard.hasImage ? attachDialog : openFileDialog).createObject(QQC2.Overlay.overlay);
dialog.chosen.connect(path => root.contentModel.addAttachment(path));
dialog.open();
}
QQC2.ToolTip.visible: hovered
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
QQC2.ToolTip.text: text

View File

@@ -5,7 +5,11 @@
#include <Kirigami/Platform/PlatformTheme>
#include "chatbarcache.h"
#include "chattextitemhelper.h"
#include "enums/chatbartype.h"
#include "enums/richformat.h"
#include "neochatroom.h"
ChatButtonHelper::ChatButtonHelper(QObject *parent)
: QObject(parent)
@@ -30,13 +34,51 @@ void ChatButtonHelper::setTextItem(ChatTextItemHelper *textItem)
m_textItem = textItem;
if (m_textItem) {
connect(m_textItem, &ChatTextItemHelper::formatChanged, this, &ChatButtonHelper::linkChanged);
connect(m_textItem, &ChatTextItemHelper::textFormatChanged, this, &ChatButtonHelper::textFormatChanged);
connect(m_textItem, &ChatTextItemHelper::roomChanged, this, [this]() {
if (m_textItem->room() && m_textItem->type() != ChatBarType::None) {
const auto cache = m_textItem->room()->cacheForType(m_textItem->type());
connect(cache, &ChatBarCache::attachmentPathChanged, this, &ChatButtonHelper::richFormatEnabledChanged);
}
});
connect(m_textItem, &ChatTextItemHelper::textFormatChanged, this, &ChatButtonHelper::richFormatEnabledChanged);
connect(m_textItem, &ChatTextItemHelper::charFormatChanged, this, &ChatButtonHelper::charFormatChanged);
connect(m_textItem, &ChatTextItemHelper::styleChanged, this, &ChatButtonHelper::styleChanged);
connect(m_textItem, &ChatTextItemHelper::listChanged, this, &ChatButtonHelper::listChanged);
}
Q_EMIT textItemChanged();
Q_EMIT richFormatEnabledChanged();
}
bool ChatButtonHelper::richFormatEnabled() const
{
if (!m_textItem) {
return false;
}
const auto styleAvailable = styleFormatEnabled();
if (!styleAvailable) {
return false;
}
const auto format = m_textItem->textFormat();
if (format) {
return format != Qt::PlainText;
}
return false;
}
bool ChatButtonHelper::styleFormatEnabled() const
{
if (!m_textItem) {
return false;
}
const auto room = m_textItem->room();
if (!room) {
return false;
}
if (const auto cache = room->cacheForType(m_textItem->type())) {
return cache->attachmentPath().isEmpty();
}
return true;
}
bool ChatButtonHelper::bold() const

View File

@@ -26,22 +26,32 @@ class ChatButtonHelper : public QObject
/**
* @brief Whether the text format at the current cursor is bold.
*/
Q_PROPERTY(bool bold READ bold NOTIFY textFormatChanged)
Q_PROPERTY(bool richFormatEnabled READ richFormatEnabled NOTIFY richFormatEnabledChanged)
/**
* @brief Whether the text format at the current cursor is bold.
*/
Q_PROPERTY(bool styleFormatEnabled READ styleFormatEnabled NOTIFY richFormatEnabledChanged)
/**
* @brief Whether the text format at the current cursor is bold.
*/
Q_PROPERTY(bool bold READ bold NOTIFY charFormatChanged)
/**
* @brief Whether the text format at the current cursor is italic.
*/
Q_PROPERTY(bool italic READ italic NOTIFY textFormatChanged)
Q_PROPERTY(bool italic READ italic NOTIFY charFormatChanged)
/**
* @brief Whether the text format at the current cursor is underlined.
*/
Q_PROPERTY(bool underline READ underline NOTIFY textFormatChanged)
Q_PROPERTY(bool underline READ underline NOTIFY charFormatChanged)
/**
* @brief Whether the text format at the current cursor is struckthrough.
*/
Q_PROPERTY(bool strikethrough READ strikethrough NOTIFY textFormatChanged)
Q_PROPERTY(bool strikethrough READ strikethrough NOTIFY charFormatChanged)
/**
* @brief Whether the format at the current cursor includes RichFormat::UnorderedList.
@@ -71,12 +81,12 @@ class ChatButtonHelper : public QObject
/**
* @brief The link url at the current cursor position.
*/
Q_PROPERTY(QString currentLinkUrl READ currentLinkUrl NOTIFY linkChanged)
Q_PROPERTY(QString currentLinkUrl READ currentLinkUrl NOTIFY charFormatChanged)
/**
* @brief The link url at the current cursor position.
*/
Q_PROPERTY(QString currentLinkText READ currentLinkText NOTIFY linkChanged)
Q_PROPERTY(QString currentLinkText READ currentLinkText NOTIFY charFormatChanged)
public:
explicit ChatButtonHelper(QObject *parent = nullptr);
@@ -84,6 +94,8 @@ public:
ChatTextItemHelper *textItem() const;
void setTextItem(ChatTextItemHelper *textItem);
bool richFormatEnabled() const;
bool styleFormatEnabled() const;
bool bold() const;
bool italic() const;
bool underline() const;
@@ -128,11 +140,10 @@ public:
Q_SIGNALS:
void textItemChanged();
void formatChanged();
void textFormatChanged();
void richFormatEnabledChanged();
void charFormatChanged();
void styleChanged();
void listChanged();
void linkChanged();
private:
QPointer<ChatTextItemHelper> m_textItem;