diff --git a/gpt4all-chat/CMakeLists.txt b/gpt4all-chat/CMakeLists.txt
index be503598..c9d20622 100644
--- a/gpt4all-chat/CMakeLists.txt
+++ b/gpt4all-chat/CMakeLists.txt
@@ -175,6 +175,7 @@ qt_add_qml_module(chat
icons/antenna_3.svg
icons/send_message.svg
icons/stop_generating.svg
+ icons/recycle.svg
icons/regenerate.svg
icons/caret_down.svg
icons/caret_right.svg
diff --git a/gpt4all-chat/chatviewtextprocessor.cpp b/gpt4all-chat/chatviewtextprocessor.cpp
index bade6c18..f4119276 100644
--- a/gpt4all-chat/chatviewtextprocessor.cpp
+++ b/gpt4all-chat/chatviewtextprocessor.cpp
@@ -888,6 +888,7 @@ ChatViewTextProcessor::ChatViewTextProcessor(QObject *parent)
, m_syntaxHighlighter(new SyntaxHighlighter(this))
, m_isProcessingText(false)
, m_shouldProcessText(true)
+ , m_fontPixelSize(QGuiApplication::font().pointSizeF())
{
}
@@ -933,6 +934,20 @@ void ChatViewTextProcessor::setShouldProcessText(bool b)
handleTextChanged();
}
+qreal ChatViewTextProcessor::fontPixelSize() const
+{
+ return m_fontPixelSize;
+}
+
+void ChatViewTextProcessor::setFontPixelSize(qreal sz)
+{
+ if (m_fontPixelSize == sz)
+ return;
+ m_fontPixelSize = sz;
+ emit fontPixelSizeChanged();
+ handleTextChanged();
+}
+
void traverseDocument(QTextDocument *doc, QTextFrame *frame)
{
QTextFrame *rootFrame = frame ? frame : doc->rootFrame();
@@ -1126,7 +1141,7 @@ void ChatViewTextProcessor::handleCodeBlocks()
codeBlockCharFormat.setForeground(defaultColor);
QFont monospaceFont("Courier");
- monospaceFont.setPointSize(QGuiApplication::font().pointSize() + 2);
+ monospaceFont.setPointSize(m_fontPixelSize);
if (monospaceFont.family() != "Courier") {
monospaceFont.setFamily("Monospace"); // Fallback if Courier isn't available
}
diff --git a/gpt4all-chat/chatviewtextprocessor.h b/gpt4all-chat/chatviewtextprocessor.h
index 7f2cc73e..60207f44 100644
--- a/gpt4all-chat/chatviewtextprocessor.h
+++ b/gpt4all-chat/chatviewtextprocessor.h
@@ -42,6 +42,7 @@ class ChatViewTextProcessor : public QObject
Q_OBJECT
Q_PROPERTY(QQuickTextDocument* textDocument READ textDocument WRITE setTextDocument NOTIFY textDocumentChanged())
Q_PROPERTY(bool shouldProcessText READ shouldProcessText WRITE setShouldProcessText NOTIFY shouldProcessTextChanged())
+ Q_PROPERTY(qreal fontPixelSize READ fontPixelSize WRITE setFontPixelSize NOTIFY fontPixelSizeChanged())
QML_ELEMENT
public:
explicit ChatViewTextProcessor(QObject *parent = nullptr);
@@ -57,9 +58,13 @@ public:
bool shouldProcessText() const;
void setShouldProcessText(bool b);
+ qreal fontPixelSize() const;
+ void setFontPixelSize(qreal b);
+
Q_SIGNALS:
void textDocumentChanged();
void shouldProcessTextChanged();
+ void fontPixelSizeChanged();
private Q_SLOTS:
void handleTextChanged();
@@ -75,6 +80,7 @@ private:
QColor m_headerColor;
bool m_shouldProcessText = false;
bool m_isProcessingText = false;
+ qreal m_fontPixelSize;
};
#endif // CHATVIEWTEXTPROCESSOR_H
diff --git a/gpt4all-chat/icons/close.svg b/gpt4all-chat/icons/close.svg
index 4074cd97..70772054 100644
--- a/gpt4all-chat/icons/close.svg
+++ b/gpt4all-chat/icons/close.svg
@@ -1,5 +1 @@
-
-
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/copy.svg b/gpt4all-chat/icons/copy.svg
index 5ab45b5b..1b1334c7 100644
--- a/gpt4all-chat/icons/copy.svg
+++ b/gpt4all-chat/icons/copy.svg
@@ -1,9 +1 @@
-
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/download.svg b/gpt4all-chat/icons/download.svg
index 76f56c3f..60d202b4 100644
--- a/gpt4all-chat/icons/download.svg
+++ b/gpt4all-chat/icons/download.svg
@@ -1,5 +1 @@
-
-
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/image.svg b/gpt4all-chat/icons/image.svg
index f4c46f14..25a7a765 100644
--- a/gpt4all-chat/icons/image.svg
+++ b/gpt4all-chat/icons/image.svg
@@ -1,6 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/network.svg b/gpt4all-chat/icons/network.svg
index 266f13d6..4b148276 100644
--- a/gpt4all-chat/icons/network.svg
+++ b/gpt4all-chat/icons/network.svg
@@ -1 +1 @@
-
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/question.svg b/gpt4all-chat/icons/question.svg
index 7cf18fdd..7825afec 100644
--- a/gpt4all-chat/icons/question.svg
+++ b/gpt4all-chat/icons/question.svg
@@ -1,8 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/recycle.svg b/gpt4all-chat/icons/recycle.svg
new file mode 100644
index 00000000..27cb1f08
--- /dev/null
+++ b/gpt4all-chat/icons/recycle.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/redo.svg b/gpt4all-chat/icons/redo.svg
new file mode 100644
index 00000000..6a0db9e6
--- /dev/null
+++ b/gpt4all-chat/icons/redo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/regenerate.svg b/gpt4all-chat/icons/regenerate.svg
index 016e6a52..25cdeedf 100644
--- a/gpt4all-chat/icons/regenerate.svg
+++ b/gpt4all-chat/icons/regenerate.svg
@@ -1 +1 @@
-
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/search.svg b/gpt4all-chat/icons/search.svg
index bae556fc..bf4e5058 100644
--- a/gpt4all-chat/icons/search.svg
+++ b/gpt4all-chat/icons/search.svg
@@ -1,6 +1 @@
-
-
-
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/send_message.svg b/gpt4all-chat/icons/send_message.svg
index d8650b66..ca4a8296 100644
--- a/gpt4all-chat/icons/send_message.svg
+++ b/gpt4all-chat/icons/send_message.svg
@@ -1 +1 @@
-
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/stop_generating.svg b/gpt4all-chat/icons/stop_generating.svg
index c627ac0e..72261f00 100644
--- a/gpt4all-chat/icons/stop_generating.svg
+++ b/gpt4all-chat/icons/stop_generating.svg
@@ -1 +1 @@
-
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/thumbs_down.svg b/gpt4all-chat/icons/thumbs_down.svg
index b01a82d3..4123d9ef 100644
--- a/gpt4all-chat/icons/thumbs_down.svg
+++ b/gpt4all-chat/icons/thumbs_down.svg
@@ -1,5 +1 @@
-
-
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/thumbs_up.svg b/gpt4all-chat/icons/thumbs_up.svg
index cd5efcd2..7adc0b31 100644
--- a/gpt4all-chat/icons/thumbs_up.svg
+++ b/gpt4all-chat/icons/thumbs_up.svg
@@ -1,5 +1 @@
-
-
+
\ No newline at end of file
diff --git a/gpt4all-chat/icons/undo.svg b/gpt4all-chat/icons/undo.svg
new file mode 100644
index 00000000..ced96b87
--- /dev/null
+++ b/gpt4all-chat/icons/undo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gpt4all-chat/qml/ChatView.qml b/gpt4all-chat/qml/ChatView.qml
index dca00017..8a9c268a 100644
--- a/gpt4all-chat/qml/ChatView.qml
+++ b/gpt4all-chat/qml/ChatView.qml
@@ -949,6 +949,7 @@ Rectangle {
ChatViewTextProcessor {
id: textProcessor
+ fontPixelSize: myTextArea.font.pixelSize
}
Component.onCompleted: {
@@ -1019,9 +1020,9 @@ Rectangle {
MyToolButton {
id: thumbsDown
anchors.top: thumbsUp.top
- anchors.topMargin: 10
+ anchors.topMargin: 3
anchors.left: thumbsUp.right
- anchors.leftMargin: 2
+ anchors.leftMargin: 3
width: 24
height: 24
imageWidth: width
@@ -1307,33 +1308,122 @@ Rectangle {
}
}
}
+
}
- RowLayout {
- id: conversationButtons
- anchors.bottom: textInputView.top
- anchors.horizontalCenter: textInputView.horizontalCenter
- anchors.bottomMargin: 20
- spacing: 10
- MyButton {
- textColor: theme.textColor
- visible: chatModel.count && !currentChat.isServer && currentChat.isModelLoaded
- Image {
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: 15
- source: currentChat.responseInProgress ? "qrc:/gpt4all/icons/stop_generating.svg" : "qrc:/gpt4all/icons/regenerate.svg"
+ Rectangle {
+ id: conversationTrayContent
+ anchors.bottom: conversationTrayButton.top
+ anchors.horizontalCenter: conversationTrayButton.horizontalCenter
+ width: conversationTrayContentLayout.width
+ height: conversationTrayContentLayout.height
+ color: theme.containerBackground
+ radius: 5
+ opacity: 0
+ visible: false
+ clip: true
+ z: 400
+
+ property bool isHovered: {
+ return conversationTrayButton.isHovered ||
+ resetContextButton.hovered || copyChatButton.hovered ||
+ regenerateButton.hovered || stopButton.hovered
+ }
+
+ state: conversationTrayContent.isHovered ? "expanded" : "collapsed"
+ states: [
+ State {
+ name: "expanded"
+ PropertyChanges { target: conversationTrayContent; opacity: 1 }
+ },
+ State {
+ name: "collapsed"
+ PropertyChanges { target: conversationTrayContent; opacity: 0 }
}
+ ]
+ transitions: [
+ Transition {
+ from: "collapsed"
+ to: "expanded"
+ SequentialAnimation {
+ ScriptAction {
+ script: conversationTrayContent.visible = true
+ }
+ PropertyAnimation {
+ target: conversationTrayContent
+ property: "opacity"
+ duration: 300
+ easing.type: Easing.InOutQuad
+ }
+ }
+ },
+ Transition {
+ from: "expanded"
+ to: "collapsed"
+ SequentialAnimation {
+ PropertyAnimation {
+ target: conversationTrayContent
+ property: "opacity"
+ duration: 300
+ easing.type: Easing.InOutQuad
+ }
+ ScriptAction {
+ script: conversationTrayContent.visible = false
+ }
+ }
+ }
+ ]
- leftPadding: 50
- onClicked: {
- var index = Math.max(0, chatModel.count - 1);
- var listElement = chatModel.get(index);
-
- if (currentChat.responseInProgress) {
- listElement.stopped = true
- currentChat.stopGenerating()
- } else {
+ RowLayout {
+ id: conversationTrayContentLayout
+ spacing: 0
+ MyToolButton {
+ id: resetContextButton
+ Layout.preferredWidth: 40
+ Layout.preferredHeight: 40
+ source: "qrc:/gpt4all/icons/recycle.svg"
+ imageWidth: 20
+ imageHeight: 20
+ onClicked: {
+ Network.trackChatEvent("reset_context", { "length": chatModel.count })
+ currentChat.reset();
+ currentChat.processSystemPrompt();
+ }
+ ToolTip.visible: resetContextButton.hovered
+ ToolTip.text: qsTr("Erase and reset chat session")
+ }
+ MyToolButton {
+ id: copyChatButton
+ Layout.preferredWidth: 40
+ Layout.preferredHeight: 40
+ source: "qrc:/gpt4all/icons/copy.svg"
+ imageWidth: 20
+ imageHeight: 20
+ TextEdit{
+ id: copyEdit
+ visible: false
+ }
+ onClicked: {
+ var conversation = getConversation()
+ copyEdit.text = conversation
+ copyEdit.selectAll()
+ copyEdit.copy()
+ copyMessage.open()
+ }
+ ToolTip.visible: copyChatButton.hovered
+ ToolTip.text: qsTr("Copy chat session to clipboard")
+ }
+ MyToolButton {
+ id: regenerateButton
+ Layout.preferredWidth: 40
+ Layout.preferredHeight: 40
+ source: "qrc:/gpt4all/icons/regenerate.svg"
+ imageWidth: 20
+ imageHeight: 20
+ visible: chatModel.count && !currentChat.isServer && currentChat.isModelLoaded && !currentChat.responseInProgress
+ onClicked: {
+ var index = Math.max(0, chatModel.count - 1);
+ var listElement = chatModel.get(index);
currentChat.regenerateResponse()
if (chatModel.count) {
if (listElement.name === qsTr("Response: ")) {
@@ -1346,51 +1436,89 @@ Rectangle {
}
}
}
+ ToolTip.visible: regenerateButton.hovered
+ ToolTip.text: qsTr("Redo last chat response")
}
+ MyToolButton {
+ id: stopButton
+ Layout.preferredWidth: 40
+ Layout.preferredHeight: 40
+ source: "qrc:/gpt4all/icons/stop_generating.svg"
+ imageWidth: 20
+ imageHeight: 20
+ visible: currentChat.responseInProgress
+ onClicked: {
+ var index = Math.max(0, chatModel.count - 1);
+ var listElement = chatModel.get(index);
+ listElement.stopped = true
+ currentChat.stopGenerating()
+ }
+ ToolTip.visible: stopButton.hovered
+ ToolTip.text: qsTr("Stop the current response generation")
+ }
+ }
+ }
- borderWidth: 1
- backgroundColor: theme.conversationButtonBackground
- backgroundColorHovered: theme.conversationButtonBackgroundHovered
- backgroundRadius: 5
- padding: 15
- topPadding: 8
- bottomPadding: 8
- text: currentChat.responseInProgress ? qsTr("Stop generating") : qsTr("Regenerate response")
- fontPixelSize: theme.fontSizeSmall
- Accessible.description: qsTr("Controls generation of the response")
+ Item {
+ id: conversationTrayButton
+ anchors.bottom: textInputView.top
+ anchors.horizontalCenter: textInputView.horizontalCenter
+ width: 30
+ height: 30
+ visible: chatModel.count && !currentChat.isServer && currentChat.isModelLoaded
+ property bool isHovered: conversationTrayMouseAreaButton.containsMouse
+ MouseArea {
+ id: conversationTrayMouseAreaButton
+ anchors.fill: parent
+ hoverEnabled: true
+ }
+ Text {
+ id: conversationTrayTextButton
+ anchors.horizontalCenter: parent.horizontalCenter
+ horizontalAlignment: Qt.AlignHCenter
+ leftPadding: 5
+ rightPadding: 5
+ text: "\u00B7\u00B7\u00B7"
+ color: theme.textColor
+ font.pixelSize: 20 // fixed size
+ }
+ }
+
+ MyButton {
+ anchors.bottom: textInputView.top
+ anchors.horizontalCenter: textInputView.horizontalCenter
+ anchors.bottomMargin: 20
+ textColor: theme.textColor
+ visible: !currentChat.isServer
+ && !currentChat.isModelLoaded
+ && currentChat.modelLoadingError === ""
+ && !currentChat.trySwitchContextInProgress
+ && !currentChat.isCurrentlyLoading
+ && currentModelName() !== ""
+
+ Image {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: 15
+ sourceSize.width: 15
+ sourceSize.height: 15
+ source: "qrc:/gpt4all/icons/regenerate.svg"
+ }
+ leftPadding: 40
+ onClicked: {
+ currentChat.reloadModel();
}
- MyButton {
- textColor: theme.textColor
- visible: !currentChat.isServer
- && !currentChat.isModelLoaded
- && currentChat.modelLoadingError === ""
- && !currentChat.trySwitchContextInProgress
- && !currentChat.isCurrentlyLoading
- && currentModelName() !== ""
-
- Image {
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: 15
- source: "qrc:/gpt4all/icons/regenerate.svg"
- }
- leftPadding: 50
- onClicked: {
- currentChat.reloadModel();
- }
-
- borderWidth: 1
- backgroundColor: theme.conversationButtonBackground
- backgroundColorHovered: theme.conversationButtonBackgroundHovered
- backgroundRadius: 5
- padding: 15
- topPadding: 8
- bottomPadding: 8
- text: qsTr("Reload \u00B7 ") + currentChat.modelInfo.name
- fontPixelSize: theme.fontSizeSmall
- Accessible.description: qsTr("Reloads the model")
- }
+ borderWidth: 1
+ backgroundColor: theme.conversationButtonBackground
+ backgroundColorHovered: theme.conversationButtonBackgroundHovered
+ backgroundRadius: 5
+ padding: 15
+ topPadding: 8
+ bottomPadding: 8
+ text: qsTr("Reload \u00B7 ") + currentChat.modelInfo.name
+ fontPixelSize: theme.fontSizeSmall
+ Accessible.description: qsTr("Reloads the model")
}
Text {
diff --git a/gpt4all-chat/qml/Theme.qml b/gpt4all-chat/qml/Theme.qml
index eab8aece..880d674f 100644
--- a/gpt4all-chat/qml/Theme.qml
+++ b/gpt4all-chat/qml/Theme.qml
@@ -518,7 +518,7 @@ QtObject {
case "Dark":
return accentColor;
default:
- return accentColor;
+ return black;
}
}
@@ -529,7 +529,7 @@ QtObject {
case "Dark":
return darkwhite;
default:
- return black;
+ return accentColor;
}
}
@@ -740,7 +740,7 @@ QtObject {
case "Dark":
return green400;
default:
- return green400;
+ return black;
}
}