diff --git a/gpt4all-chat/chatmodel.h b/gpt4all-chat/chatmodel.h index 9313dff6..f061ccf7 100644 --- a/gpt4all-chat/chatmodel.h +++ b/gpt4all-chat/chatmodel.h @@ -188,11 +188,6 @@ public: } } - Q_INVOKABLE void forceUpdate(int index) - { - emit dataChanged(createIndex(index, 0), createIndex(index, 0), {ValueRole}); - } - Q_INVOKABLE void updateValue(int index, const QString &value) { if (index < 0 || index >= m_chatItems.size()) return; @@ -201,6 +196,7 @@ public: if (item.value != value) { item.value = value; emit dataChanged(createIndex(index, 0), createIndex(index, 0), {ValueRole}); + emit valueChanged(index, value); } } @@ -468,6 +464,7 @@ public: Q_SIGNALS: void countChanged(); + void valueChanged(int index, const QString &value); private: diff --git a/gpt4all-chat/chatviewtextprocessor.cpp b/gpt4all-chat/chatviewtextprocessor.cpp index e1e9805d..e057017c 100644 --- a/gpt4all-chat/chatviewtextprocessor.cpp +++ b/gpt4all-chat/chatviewtextprocessor.cpp @@ -771,9 +771,8 @@ void SyntaxHighlighter::highlightBlock(const QString &text) // chat class to populate the clipboard. ChatViewTextProcessor::ChatViewTextProcessor(QObject *parent) : QObject{parent} - , m_textDocument(nullptr) + , m_quickTextDocument(nullptr) , m_syntaxHighlighter(new SyntaxHighlighter(this)) - , m_isProcessingText(false) , m_shouldProcessText(true) , m_fontPixelSize(QGuiApplication::font().pointSizeF()) { @@ -781,17 +780,19 @@ ChatViewTextProcessor::ChatViewTextProcessor(QObject *parent) QQuickTextDocument* ChatViewTextProcessor::textDocument() const { - return m_textDocument; + return m_quickTextDocument; } -void ChatViewTextProcessor::setTextDocument(QQuickTextDocument* textDocument) +void ChatViewTextProcessor::setTextDocument(QQuickTextDocument* quickTextDocument) { - if (m_textDocument) - disconnect(m_textDocument->textDocument(), &QTextDocument::contentsChanged, this, &ChatViewTextProcessor::handleTextChanged); + m_quickTextDocument = quickTextDocument; + m_syntaxHighlighter->setDocument(m_quickTextDocument->textDocument()); + handleTextChanged(); +} - m_textDocument = textDocument; - m_syntaxHighlighter->setDocument(m_textDocument->textDocument()); - connect(m_textDocument->textDocument(), &QTextDocument::contentsChanged, this, &ChatViewTextProcessor::handleTextChanged); +void ChatViewTextProcessor::setValue(const QString &value) +{ + m_quickTextDocument->textDocument()->setPlainText(value); handleTextChanged(); } @@ -881,14 +882,12 @@ void traverseDocument(QTextDocument *doc, QTextFrame *frame) void ChatViewTextProcessor::handleTextChanged() { - if (!m_textDocument || m_isProcessingText || !m_shouldProcessText) + if (!m_quickTextDocument || !m_shouldProcessText) return; - m_isProcessingText = true; - // Force full layout of the text document to work around a bug in Qt // TODO(jared): report the Qt bug and link to the report here - QTextDocument* doc = m_textDocument->textDocument(); + QTextDocument* doc = m_quickTextDocument->textDocument(); (void)doc->documentLayout()->documentSize(); handleCodeBlocks(); @@ -899,12 +898,11 @@ void ChatViewTextProcessor::handleTextChanged() QTextCursor cursor(doc); QString invisibleCharacter = QString(QChar(0xFEFF)); cursor.insertText(invisibleCharacter, QTextCharFormat()); - m_isProcessingText = false; } void ChatViewTextProcessor::handleCodeBlocks() { - QTextDocument* doc = m_textDocument->textDocument(); + QTextDocument* doc = m_quickTextDocument->textDocument(); QTextCursor cursor(doc); QTextCharFormat textFormat; @@ -1081,7 +1079,7 @@ void replaceAndInsertMarkdown(int startIndex, int endIndex, QTextDocument *doc) void ChatViewTextProcessor::handleMarkdown() { - QTextDocument* doc = m_textDocument->textDocument(); + QTextDocument* doc = m_quickTextDocument->textDocument(); QTextCursor cursor(doc); QVector> codeBlockPositions; diff --git a/gpt4all-chat/chatviewtextprocessor.h b/gpt4all-chat/chatviewtextprocessor.h index 33ddbfd4..c99411bd 100644 --- a/gpt4all-chat/chatviewtextprocessor.h +++ b/gpt4all-chat/chatviewtextprocessor.h @@ -96,6 +96,7 @@ public: QQuickTextDocument* textDocument() const; void setTextDocument(QQuickTextDocument* textDocument); + Q_INVOKABLE void setValue(const QString &value); Q_INVOKABLE bool tryCopyAtPosition(int position) const; bool shouldProcessText() const; @@ -119,12 +120,11 @@ private Q_SLOTS: void handleMarkdown(); private: - QQuickTextDocument *m_textDocument; + QQuickTextDocument *m_quickTextDocument; SyntaxHighlighter *m_syntaxHighlighter; QVector m_links; QVector m_copies; bool m_shouldProcessText = false; - bool m_isProcessingText = false; qreal m_fontPixelSize; }; diff --git a/gpt4all-chat/qml/ChatView.qml b/gpt4all-chat/qml/ChatView.qml index f028bf9d..a85d94c3 100644 --- a/gpt4all-chat/qml/ChatView.qml +++ b/gpt4all-chat/qml/ChatView.qml @@ -879,7 +879,6 @@ Rectangle { Layout.fillWidth: true TextArea { id: myTextArea - text: value Layout.fillWidth: true padding: 0 color: { @@ -953,7 +952,7 @@ Rectangle { height: enabled ? implicitHeight : 0 onTriggered: { textProcessor.shouldProcessText = !textProcessor.shouldProcessText; - myTextArea.text = value + textProcessor.setValue(value); } } } @@ -974,11 +973,16 @@ Rectangle { textProcessor.codeColors.headerColor = theme.codeHeaderColor textProcessor.codeColors.backgroundColor = theme.codeBackgroundColor textProcessor.textDocument = textDocument - chatModel.forceUpdate(index); // called to trigger a reprocessing of the text + textProcessor.setValue(value); } Component.onCompleted: { resetChatViewTextProcessor(); + chatModel.valueChanged.connect(function(i, value) { + if (index === i) + textProcessor.setValue(value); + } + ); } Connections { diff --git a/gpt4all-chat/qml/HomeView.qml b/gpt4all-chat/qml/HomeView.qml index b73ccf46..b73d4a21 100644 --- a/gpt4all-chat/qml/HomeView.qml +++ b/gpt4all-chat/qml/HomeView.qml @@ -272,7 +272,7 @@ Rectangle { color: theme.conversationBackground width: subscribeLink.width RowLayout { - anchors.fill: parent + anchors.centerIn: parent MyFancyLink { id: subscribeLink Layout.alignment: Qt.AlignCenter