Separate ChatButtonHelper from ChatDocumentHandler
This commit is contained in:
@@ -25,6 +25,7 @@ ecm_add_qml_module(Chatbar GENERATE_PLUGIN_SOURCE
|
||||
NewPollDialog.qml
|
||||
TableDialog.qml
|
||||
SOURCES
|
||||
chatbuttonhelper.cpp
|
||||
styledelegatehelper.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -64,6 +64,10 @@ QQC2.ToolBar {
|
||||
buttonRow.spacing * 9 +
|
||||
3
|
||||
|
||||
readonly property ChatButtonHelper chatButtonHelper: ChatButtonHelper {
|
||||
textItem: contentModel.currentTextItem
|
||||
}
|
||||
|
||||
signal clicked
|
||||
|
||||
RowLayout {
|
||||
@@ -82,9 +86,9 @@ QQC2.ToolBar {
|
||||
text: i18nc("@action:button", "Bold")
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
checkable: true
|
||||
checked: root.focusedDocumentHandler.bold
|
||||
checked: root.chatButtonHelper.bold
|
||||
onClicked: {
|
||||
root.focusedDocumentHandler.setFormat(LibNeoChat.RichFormat.Bold);
|
||||
root.chatButtonHelper.setFormat(LibNeoChat.RichFormat.Bold);
|
||||
root.clicked()
|
||||
}
|
||||
|
||||
@@ -103,9 +107,9 @@ QQC2.ToolBar {
|
||||
text: i18nc("@action:button", "Italic")
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
checkable: true
|
||||
checked: root.focusedDocumentHandler.italic
|
||||
checked: root.chatButtonHelper.italic
|
||||
onClicked: {
|
||||
root.focusedDocumentHandler.setFormat(LibNeoChat.RichFormat.Italic);
|
||||
root.chatButtonHelper.setFormat(LibNeoChat.RichFormat.Italic);
|
||||
root.clicked()
|
||||
}
|
||||
|
||||
@@ -124,9 +128,9 @@ QQC2.ToolBar {
|
||||
text: i18nc("@action:button", "Underline")
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
checkable: true
|
||||
checked: root.focusedDocumentHandler.underline
|
||||
checked: root.chatButtonHelper.underline
|
||||
onClicked: {
|
||||
root.focusedDocumentHandler.setFormat(LibNeoChat.RichFormat.Underline);
|
||||
root.chatButtonHelper.setFormat(LibNeoChat.RichFormat.Underline);
|
||||
root.clicked();
|
||||
}
|
||||
|
||||
@@ -140,9 +144,9 @@ QQC2.ToolBar {
|
||||
text: i18nc("@action:button", "Strikethrough")
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
checkable: true
|
||||
checked: root.focusedDocumentHandler.strikethrough
|
||||
checked: root.chatButtonHelper.strikethrough
|
||||
onClicked: {
|
||||
root.focusedDocumentHandler.setFormat(LibNeoChat.RichFormat.Strikethrough);
|
||||
root.chatButtonHelper.setFormat(LibNeoChat.RichFormat.Strikethrough);
|
||||
root.clicked()
|
||||
}
|
||||
|
||||
@@ -172,9 +176,9 @@ QQC2.ToolBar {
|
||||
icon.name: "format-text-bold"
|
||||
text: i18nc("@action:button", "Bold")
|
||||
checkable: true
|
||||
checked: root.focusedDocumentHandler.bold
|
||||
checked: root.chatButtonHelper.bold
|
||||
onTriggered: {
|
||||
root.focusedDocumentHandler.setFormat(LibNeoChat.RichFormat.Bold);
|
||||
root.chatButtonHelper.setFormat(LibNeoChat.RichFormat.Bold);
|
||||
root.clicked();
|
||||
}
|
||||
}
|
||||
@@ -182,9 +186,9 @@ QQC2.ToolBar {
|
||||
icon.name: "format-text-italic"
|
||||
text: i18nc("@action:button", "Italic")
|
||||
checkable: true
|
||||
checked: root.focusedDocumentHandler.italic
|
||||
checked: root.chatButtonHelper.italic
|
||||
onTriggered: {
|
||||
root.focusedDocumentHandler.setFormat(LibNeoChat.RichFormat.Italic);
|
||||
root.chatButtonHelper.setFormat(LibNeoChat.RichFormat.Italic);
|
||||
root.clicked();
|
||||
}
|
||||
}
|
||||
@@ -192,9 +196,9 @@ QQC2.ToolBar {
|
||||
icon.name: "format-text-underline"
|
||||
text: i18nc("@action:button", "Underline")
|
||||
checkable: true
|
||||
checked: root.focusedDocumentHandler.underline
|
||||
checked: root.chatButtonHelper.underline
|
||||
onTriggered: {
|
||||
root.focusedDocumentHandler.setFormat(LibNeoChat.RichFormat.Underline);
|
||||
root.chatButtonHelper.setFormat(LibNeoChat.RichFormat.Underline);
|
||||
root.clicked();
|
||||
}
|
||||
}
|
||||
@@ -202,9 +206,9 @@ QQC2.ToolBar {
|
||||
icon.name: "format-text-strikethrough"
|
||||
text: i18nc("@action:button", "Strikethrough")
|
||||
checkable: true
|
||||
checked: root.focusedDocumentHandler.strikethrough
|
||||
checked: root.chatButtonHelper.strikethrough
|
||||
onTriggered: {
|
||||
root.focusedDocumentHandler.setFormat(LibNeoChat.RichFormat.Strikethrough);
|
||||
root.chatButtonHelper.setFormat(LibNeoChat.RichFormat.Strikethrough);
|
||||
root.clicked();
|
||||
}
|
||||
}
|
||||
@@ -227,9 +231,9 @@ QQC2.ToolBar {
|
||||
text: i18nc("@action:button", "Unordered List")
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
checkable: true
|
||||
checked: root.focusedDocumentHandler.currentListStyle === 1
|
||||
checked: root.chatButtonHelper.unorderedList
|
||||
onClicked: {
|
||||
root.focusedDocumentHandler.setFormat(LibNeoChat.RichFormat.UnorderedList);
|
||||
root.chatButtonHelper.setFormat(LibNeoChat.RichFormat.UnorderedList);
|
||||
root.clicked();
|
||||
}
|
||||
|
||||
@@ -243,9 +247,9 @@ QQC2.ToolBar {
|
||||
text: i18nc("@action:button", "Ordered List")
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
checkable: true
|
||||
checked: root.focusedDocumentHandler.currentListStyle === 4
|
||||
checked: root.chatButtonHelper.orderedlist
|
||||
onClicked: {
|
||||
root.focusedDocumentHandler.setFormat(LibNeoChat.RichFormat.OrderedList);
|
||||
root.chatButtonHelper.setFormat(LibNeoChat.RichFormat.OrderedList);
|
||||
root.clicked();
|
||||
}
|
||||
|
||||
@@ -256,10 +260,11 @@ QQC2.ToolBar {
|
||||
QQC2.ToolButton {
|
||||
id: indentAction
|
||||
icon.name: "format-indent-more"
|
||||
enabled: root.contentModel.focusType !== LibNeoChat.MessageComponentType.Code && root.chatButtonHelper.canIndentListMore
|
||||
text: i18nc("@action:button", "Increase List Level")
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
onClicked: {
|
||||
root.focusedDocumentHandler.indentListMore();
|
||||
root.chatButtonHelper.indentListMore();
|
||||
root.clicked();
|
||||
}
|
||||
|
||||
@@ -270,10 +275,11 @@ QQC2.ToolBar {
|
||||
QQC2.ToolButton {
|
||||
id: dedentAction
|
||||
icon.name: "format-indent-less"
|
||||
enabled: root.contentModel.focusType !== LibNeoChat.MessageComponentType.Code && root.chatButtonHelper.canIndentListLess
|
||||
text: i18nc("@action:button", "Decrease List Level")
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
onClicked: {
|
||||
root.focusedDocumentHandler.indentListLess();
|
||||
root.chatButtonHelper.indentListLess();
|
||||
root.clicked();
|
||||
}
|
||||
|
||||
@@ -303,7 +309,7 @@ QQC2.ToolBar {
|
||||
icon.name: "format-list-unordered"
|
||||
text: i18nc("@action:button", "Unordered List")
|
||||
onTriggered: {
|
||||
root.focusedDocumentHandler.setFormat(LibNeoChat.RichFormat.UnorderedList);
|
||||
root.chatButtonHelper.setFormat(LibNeoChat.RichFormat.UnorderedList);
|
||||
root.clicked();
|
||||
}
|
||||
}
|
||||
@@ -311,7 +317,7 @@ QQC2.ToolBar {
|
||||
icon.name: "format-list-ordered"
|
||||
text: i18nc("@action:button", "Ordered List")
|
||||
onTriggered: {
|
||||
root.focusedDocumentHandler.setFormat(LibNeoChat.RichFormat.OrderedList);
|
||||
root.chatButtonHelper.setFormat(LibNeoChat.RichFormat.OrderedList);
|
||||
root.clicked();
|
||||
}
|
||||
}
|
||||
@@ -319,7 +325,7 @@ QQC2.ToolBar {
|
||||
icon.name: "format-indent-more"
|
||||
text: i18nc("@action:button", "Increase List Level")
|
||||
onTriggered: {
|
||||
root.focusedDocumentHandler.indentListMore();
|
||||
root.chatButtonHelper.indentListMore();
|
||||
root.clicked();
|
||||
}
|
||||
}
|
||||
@@ -327,7 +333,7 @@ QQC2.ToolBar {
|
||||
icon.name: "format-indent-less"
|
||||
text: i18nc("@action:button", "Decrease List Level")
|
||||
onTriggered: {
|
||||
root.focusedDocumentHandler.indentListLess();
|
||||
root.chatButtonHelper.indentListLess();
|
||||
root.clicked();
|
||||
}
|
||||
}
|
||||
@@ -355,6 +361,7 @@ QQC2.ToolBar {
|
||||
StylePicker {
|
||||
id: styleMenu
|
||||
chatContentModel: root.contentModel
|
||||
chatButtonHelper: root.chatButtonHelper
|
||||
|
||||
onClosed: root.clicked()
|
||||
}
|
||||
@@ -392,11 +399,11 @@ QQC2.ToolBar {
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
onClicked: {
|
||||
let dialog = linkDialog.createObject(QQC2.Overlay.overlay, {
|
||||
linkText: root.focusedDocumentHandler.currentLinkText(),
|
||||
linkUrl: root.focusedDocumentHandler.currentLinkUrl()
|
||||
linkText: root.chatButtonHelper.currentLinkText,
|
||||
linkUrl: root.chatButtonHelper.currentLinkUrl
|
||||
})
|
||||
dialog.onAccepted.connect(() => {
|
||||
root.focusedDocumentHandler.updateLink(dialog.linkUrl, dialog.linkText)
|
||||
root.chatButtonHelper.updateLink(dialog.linkUrl, dialog.linkText)
|
||||
root.clicked();
|
||||
});
|
||||
dialog.open();
|
||||
@@ -583,7 +590,7 @@ QQC2.ToolBar {
|
||||
currentRoom: root.room
|
||||
|
||||
onChosen: emoji => {
|
||||
root.focusedDocumentHandler.insertText(emoji);
|
||||
root.chatButtonHelper.insertText(emoji);
|
||||
close();
|
||||
}
|
||||
onClosed: if (emojiButton.checked) {
|
||||
|
||||
@@ -16,6 +16,7 @@ QQC2.Popup {
|
||||
id: root
|
||||
|
||||
required property MessageContent.ChatBarMessageContentModel chatContentModel
|
||||
required property ChatButtonHelper chatButtonHelper
|
||||
readonly property LibNeoChat.ChatDocumentHandler focusedDocumentHandler: chatContentModel.focusedDocumentHandler
|
||||
|
||||
y: -implicitHeight
|
||||
@@ -47,7 +48,7 @@ QQC2.Popup {
|
||||
) {
|
||||
root.chatContentModel.insertStyleAtCursor(styleDelegate.index);
|
||||
} else {
|
||||
root.focusedDocumentHandler.setFormat(styleDelegate.index);
|
||||
root.chatButtonHelper.setFormat(styleDelegate.index);
|
||||
}
|
||||
root.close();
|
||||
}
|
||||
|
||||
258
src/chatbar/chatbuttonhelper.cpp
Normal file
258
src/chatbar/chatbuttonhelper.cpp
Normal file
@@ -0,0 +1,258 @@
|
||||
// SPDX-FileCopyrightText: 2025 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "chatbuttonhelper.h"
|
||||
|
||||
#include <Kirigami/Platform/PlatformTheme>
|
||||
|
||||
#include "enums/richformat.h"
|
||||
|
||||
ChatButtonHelper::ChatButtonHelper(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QmlTextItemWrapper *ChatButtonHelper::textItem() const
|
||||
{
|
||||
return m_textItem;
|
||||
}
|
||||
|
||||
void ChatButtonHelper::setTextItem(QmlTextItemWrapper *textItem)
|
||||
{
|
||||
if (textItem == m_textItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_textItem) {
|
||||
m_textItem->disconnect(this);
|
||||
}
|
||||
|
||||
m_textItem = textItem;
|
||||
|
||||
if (m_textItem) {
|
||||
connect(m_textItem, &QmlTextItemWrapper::textItemChanged, this, &ChatButtonHelper::textItemChanged);
|
||||
connect(m_textItem, &QmlTextItemWrapper::formatChanged, this, &ChatButtonHelper::linkChanged);
|
||||
connect(m_textItem, &QmlTextItemWrapper::textFormatChanged, this, &ChatButtonHelper::textFormatChanged);
|
||||
connect(m_textItem, &QmlTextItemWrapper::styleChanged, this, &ChatButtonHelper::styleChanged);
|
||||
connect(m_textItem, &QmlTextItemWrapper::listChanged, this, &ChatButtonHelper::listChanged);
|
||||
}
|
||||
|
||||
Q_EMIT textItemChanged();
|
||||
}
|
||||
|
||||
bool ChatButtonHelper::bold() const
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return false;
|
||||
}
|
||||
return m_textItem->formatsAtCursor().contains(RichFormat::Bold);
|
||||
}
|
||||
|
||||
bool ChatButtonHelper::italic() const
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return false;
|
||||
}
|
||||
return m_textItem->formatsAtCursor().contains(RichFormat::Italic);
|
||||
}
|
||||
|
||||
bool ChatButtonHelper::underline() const
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return false;
|
||||
}
|
||||
return m_textItem->formatsAtCursor().contains(RichFormat::Underline);
|
||||
}
|
||||
|
||||
bool ChatButtonHelper::strikethrough() const
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return false;
|
||||
}
|
||||
return m_textItem->formatsAtCursor().contains(RichFormat::Strikethrough);
|
||||
}
|
||||
|
||||
bool ChatButtonHelper::unorderedList() const
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return false;
|
||||
}
|
||||
return m_textItem->formatsAtCursor().contains(RichFormat::UnorderedList);
|
||||
}
|
||||
|
||||
bool ChatButtonHelper::orderedList() const
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return false;
|
||||
}
|
||||
return m_textItem->formatsAtCursor().contains(RichFormat::OrderedList);
|
||||
}
|
||||
|
||||
void ChatButtonHelper::setFormat(RichFormat::Format format)
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return;
|
||||
}
|
||||
m_textItem->mergeFormatOnCursor(format);
|
||||
}
|
||||
|
||||
bool ChatButtonHelper::canIndentListMore() const
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return false;
|
||||
}
|
||||
return m_textItem->canIndentListMoreAtCursor();
|
||||
}
|
||||
|
||||
bool ChatButtonHelper::canIndentListLess() const
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return false;
|
||||
}
|
||||
return m_textItem->canIndentListLessAtCursor();
|
||||
}
|
||||
|
||||
void ChatButtonHelper::indentListMore()
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return;
|
||||
}
|
||||
m_textItem->indentListMoreAtCursor();
|
||||
}
|
||||
|
||||
void ChatButtonHelper::indentListLess()
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return;
|
||||
}
|
||||
m_textItem->indentListLessAtCursor();
|
||||
}
|
||||
|
||||
void ChatButtonHelper::insertText(const QString &text)
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return;
|
||||
}
|
||||
m_textItem->textCursor().insertText(text);
|
||||
}
|
||||
|
||||
QString ChatButtonHelper::currentLinkUrl() const
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return {};
|
||||
}
|
||||
return m_textItem->textCursor().charFormat().anchorHref();
|
||||
}
|
||||
|
||||
void ChatButtonHelper::selectLinkText(QTextCursor &cursor) const
|
||||
{
|
||||
// If the cursor is on a link, select the text of the link.
|
||||
if (cursor.charFormat().isAnchor()) {
|
||||
const QString aHref = cursor.charFormat().anchorHref();
|
||||
|
||||
// Move cursor to start of link
|
||||
while (cursor.charFormat().anchorHref() == aHref) {
|
||||
if (cursor.atStart()) {
|
||||
break;
|
||||
}
|
||||
cursor.setPosition(cursor.position() - 1);
|
||||
}
|
||||
if (cursor.charFormat().anchorHref() != aHref) {
|
||||
cursor.setPosition(cursor.position() + 1, QTextCursor::KeepAnchor);
|
||||
}
|
||||
|
||||
// Move selection to the end of the link
|
||||
while (cursor.charFormat().anchorHref() == aHref) {
|
||||
if (cursor.atEnd()) {
|
||||
break;
|
||||
}
|
||||
const int oldPosition = cursor.position();
|
||||
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
|
||||
// Wordaround Qt Bug. when we have a table.
|
||||
// FIXME selection url
|
||||
if (oldPosition == cursor.position()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cursor.charFormat().anchorHref() != aHref) {
|
||||
cursor.setPosition(cursor.position() - 1, QTextCursor::KeepAnchor);
|
||||
}
|
||||
} else if (cursor.hasSelection()) {
|
||||
// Nothing to do. Using the currently selected text as the link text.
|
||||
} else {
|
||||
// Select current word
|
||||
cursor.movePosition(QTextCursor::StartOfWord);
|
||||
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
|
||||
}
|
||||
}
|
||||
|
||||
QString ChatButtonHelper::currentLinkText() const
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return {};
|
||||
}
|
||||
QTextCursor cursor = m_textItem->textCursor();
|
||||
selectLinkText(cursor);
|
||||
return cursor.selectedText();
|
||||
}
|
||||
|
||||
void ChatButtonHelper::updateLink(const QString &linkUrl, const QString &linkText)
|
||||
{
|
||||
if (!m_textItem) {
|
||||
return;
|
||||
}
|
||||
auto cursor = m_textItem->textCursor();
|
||||
selectLinkText(cursor);
|
||||
|
||||
cursor.beginEditBlock();
|
||||
|
||||
if (!cursor.hasSelection()) {
|
||||
cursor.select(QTextCursor::WordUnderCursor);
|
||||
}
|
||||
|
||||
const auto originalFormat = cursor.charFormat();
|
||||
auto format = cursor.charFormat();
|
||||
// Save original format to create an extra space with the existing char
|
||||
// format for the block
|
||||
if (!linkUrl.isEmpty()) {
|
||||
// Add link details
|
||||
format.setAnchor(true);
|
||||
format.setAnchorHref(linkUrl);
|
||||
// Workaround for QTBUG-1814:
|
||||
// Link formatting does not get applied immediately when setAnchor(true)
|
||||
// is called. So the formatting needs to be applied manually.
|
||||
format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
|
||||
|
||||
const auto theme = static_cast<Kirigami::Platform::PlatformTheme *>(qmlAttachedPropertiesObject<Kirigami::Platform::PlatformTheme>(this, true));
|
||||
format.setUnderlineColor(theme->linkColor());
|
||||
format.setForeground(theme->linkColor());
|
||||
} else {
|
||||
// Remove link details
|
||||
format.setAnchor(false);
|
||||
format.setAnchorHref(QString());
|
||||
// Workaround for QTBUG-1814:
|
||||
// Link formatting does not get removed immediately when setAnchor(false)
|
||||
// is called. So the formatting needs to be applied manually.
|
||||
QTextDocument defaultTextDocument;
|
||||
QTextCharFormat defaultCharFormat = defaultTextDocument.begin().charFormat();
|
||||
|
||||
format.setUnderlineStyle(defaultCharFormat.underlineStyle());
|
||||
format.setUnderlineColor(defaultCharFormat.underlineColor());
|
||||
format.setForeground(defaultCharFormat.foreground());
|
||||
}
|
||||
|
||||
// Insert link text specified in dialog, otherwise write out url.
|
||||
QString _linkText;
|
||||
if (!linkText.isEmpty()) {
|
||||
_linkText = linkText;
|
||||
} else {
|
||||
_linkText = linkUrl;
|
||||
}
|
||||
cursor.insertText(_linkText, format);
|
||||
if (cursor.atBlockEnd()) {
|
||||
cursor.insertText(u" "_s, originalFormat);
|
||||
}
|
||||
cursor.endEditBlock();
|
||||
}
|
||||
|
||||
#include "moc_chatbuttonhelper.cpp"
|
||||
135
src/chatbar/chatbuttonhelper.h
Normal file
135
src/chatbar/chatbuttonhelper.h
Normal file
@@ -0,0 +1,135 @@
|
||||
// SPDX-FileCopyrightText: 2025 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include "qmltextitemwrapper.h"
|
||||
|
||||
class ChatButtonHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
/**
|
||||
* @brief The text item that the helper is interfacing with.
|
||||
*
|
||||
* This is a QQuickItem that is a TextEdit (or inherited from) wrapped in a QmlTextItemWrapper
|
||||
* to provide easy access to properties and basic QTextDocument manipulation.
|
||||
*
|
||||
* @sa TextEdit, QTextDocument, QmlTextItemWrapper
|
||||
*/
|
||||
Q_PROPERTY(QmlTextItemWrapper *textItem READ textItem WRITE setTextItem NOTIFY textItemChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the text format at the current cursor is bold.
|
||||
*/
|
||||
Q_PROPERTY(bool bold READ bold NOTIFY textFormatChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the text format at the current cursor is italic.
|
||||
*/
|
||||
Q_PROPERTY(bool italic READ italic NOTIFY textFormatChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the text format at the current cursor is underlined.
|
||||
*/
|
||||
Q_PROPERTY(bool underline READ underline NOTIFY textFormatChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the text format at the current cursor is struckthrough.
|
||||
*/
|
||||
Q_PROPERTY(bool strikethrough READ strikethrough NOTIFY textFormatChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the format at the current cursor includes RichFormat::UnorderedList.
|
||||
*/
|
||||
Q_PROPERTY(bool unorderedList READ unorderedList NOTIFY listChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the format at the current cursor includes RichFormat::OrderedList.
|
||||
*/
|
||||
Q_PROPERTY(bool orderedList READ orderedList NOTIFY listChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the list at the current cursor can be indented one level more.
|
||||
*/
|
||||
Q_PROPERTY(bool canIndentListMore READ canIndentListMore NOTIFY listChanged)
|
||||
|
||||
/**
|
||||
* @brief Whether the list at the current cursor can be indented one level less.
|
||||
*/
|
||||
Q_PROPERTY(bool canIndentListLess READ canIndentListLess NOTIFY listChanged)
|
||||
|
||||
/**
|
||||
* @brief The link url at the current cursor position.
|
||||
*/
|
||||
Q_PROPERTY(QString currentLinkUrl READ currentLinkUrl NOTIFY linkChanged)
|
||||
|
||||
/**
|
||||
* @brief The link url at the current cursor position.
|
||||
*/
|
||||
Q_PROPERTY(QString currentLinkText READ currentLinkText NOTIFY linkChanged)
|
||||
|
||||
public:
|
||||
explicit ChatButtonHelper(QObject *parent = nullptr);
|
||||
|
||||
QmlTextItemWrapper *textItem() const;
|
||||
void setTextItem(QmlTextItemWrapper *textItem);
|
||||
|
||||
bool bold() const;
|
||||
bool italic() const;
|
||||
bool underline() const;
|
||||
bool strikethrough() const;
|
||||
bool unorderedList() const;
|
||||
bool orderedList() const;
|
||||
|
||||
/**
|
||||
* @brief Apply the given format at the current cursor position.
|
||||
*/
|
||||
Q_INVOKABLE void setFormat(RichFormat::Format format);
|
||||
|
||||
bool canIndentListMore() const;
|
||||
bool canIndentListLess() const;
|
||||
|
||||
/**
|
||||
* @brief Indent the list at the current cursor one level more.
|
||||
*/
|
||||
Q_INVOKABLE void indentListMore();
|
||||
|
||||
/**
|
||||
* @brief Indent the list at the current cursor one level less.
|
||||
*/
|
||||
Q_INVOKABLE void indentListLess();
|
||||
|
||||
/**
|
||||
* @brief Insert text at the current cursor position.
|
||||
*/
|
||||
Q_INVOKABLE void insertText(const QString &text);
|
||||
|
||||
QString currentLinkUrl() const;
|
||||
QString currentLinkText() const;
|
||||
|
||||
/**
|
||||
* @brief Update the link at the current cursor position.
|
||||
*
|
||||
* This will replace any selected text of the word next to the cursor with the
|
||||
* given text and will link to the given url.
|
||||
*/
|
||||
Q_INVOKABLE void updateLink(const QString &linkUrl, const QString &linkText);
|
||||
|
||||
Q_SIGNALS:
|
||||
void textItemChanged();
|
||||
void formatChanged();
|
||||
void textFormatChanged();
|
||||
void styleChanged();
|
||||
void listChanged();
|
||||
void linkChanged();
|
||||
|
||||
private:
|
||||
QPointer<QmlTextItemWrapper> m_textItem;
|
||||
|
||||
void selectLinkText(QTextCursor &cursor) const;
|
||||
};
|
||||
Reference in New Issue
Block a user