diff --git a/gpt4all-chat/chatviewtextprocessor.cpp b/gpt4all-chat/chatviewtextprocessor.cpp index f4119276..f8dad8a1 100644 --- a/gpt4all-chat/chatviewtextprocessor.cpp +++ b/gpt4all-chat/chatviewtextprocessor.cpp @@ -41,29 +41,6 @@ enum Language { Markdown }; -// TODO (Adam) These should be themeable and not hardcoded since they are quite harsh on the eyes in -// light mode. - -static QColor defaultColor = "#d1d5db"; // white -static QColor keywordColor = "#2e95d3"; // blue -static QColor functionColor = "#f22c3d"; // red -static QColor functionCallColor = "#e9950c"; // orange -static QColor commentColor = "#808080"; // gray -static QColor stringColor = "#00a37d"; // green -static QColor numberColor = "#df3079"; // fuchsia -static QColor preprocessorColor = keywordColor; -static QColor typeColor = numberColor; -static QColor arrowColor = functionColor; -static QColor commandColor = functionCallColor; -static QColor variableColor = numberColor; -static QColor keyColor = functionColor; -static QColor valueColor = stringColor; -static QColor parameterColor = stringColor; -static QColor attributeNameColor = numberColor; -static QColor attributeValueColor = stringColor; -static QColor specialCharacterColor = functionColor; -static QColor doctypeColor = commentColor; - static Language stringToLanguage(const QString &language) { if (language == "python") @@ -101,11 +78,62 @@ static Language stringToLanguage(const QString &language) return None; } +enum Code { + Default, + Keyword, + Function, + FunctionCall, + Comment, + String, + Number, + Header, + Preprocessor, + Type, + Arrow, + Command, + Variable, + Key, + Value, + Parameter, + AttributeName, + AttributeValue, + SpecialCharacter, + DocType +}; + struct HighlightingRule { QRegularExpression pattern; - QTextCharFormat format; + Code format; }; +static QColor formatToColor(Code c, const CodeColors &colors) +{ + switch (c) { + case Default: return colors.defaultColor; + case Keyword: return colors.keywordColor; + case Function: return colors.functionColor; + case FunctionCall: return colors.functionCallColor; + case Comment: return colors.commentColor; + case String: return colors.stringColor; + case Number: return colors.numberColor; + case Header: return colors.headerColor; + case Preprocessor: return colors.preprocessorColor; + case Type: return colors.typeColor; + case Arrow: return colors.arrowColor; + case Command: return colors.commandColor; + case Variable: return colors.variableColor; + case Key: return colors.keyColor; + case Value: return colors.valueColor; + case Parameter: return colors.parameterColor; + case AttributeName: return colors.attributeNameColor; + case AttributeValue: return colors.attributeValueColor; + case SpecialCharacter: return colors.specialCharacterColor; + case DocType: return colors.doctypeColor; + default: Q_UNREACHABLE(); + } + return QColor(); +} + static QVector pythonHighlightingRules() { static QVector highlightingRules; @@ -113,32 +141,22 @@ static QVector pythonHighlightingRules() HighlightingRule rule; - QTextCharFormat defaultFormat; - defaultFormat.setForeground(defaultColor); rule.pattern = QRegularExpression(".*"); - rule.format = defaultFormat; + rule.format = Default; highlightingRules.append(rule); - QTextCharFormat functionCallFormat; - functionCallFormat.setForeground(functionCallColor); rule.pattern = QRegularExpression("\\b(\\w+)\\s*(?=\\()"); - rule.format = functionCallFormat; + rule.format = FunctionCall; highlightingRules.append(rule); - QTextCharFormat functionFormat; - functionFormat.setForeground(functionColor); rule.pattern = QRegularExpression("\\bdef\\s+(\\w+)\\b"); - rule.format = functionFormat; + rule.format = Function; highlightingRules.append(rule); - QTextCharFormat numberFormat; - numberFormat.setForeground(numberColor); rule.pattern = QRegularExpression("\\b[0-9]*\\.?[0-9]+\\b"); - rule.format = numberFormat; + rule.format = Number; highlightingRules.append(rule); - QTextCharFormat keywordFormat; - keywordFormat.setForeground(keywordColor); QStringList keywordPatterns = { "\\bdef\\b", "\\bclass\\b", "\\bif\\b", "\\belse\\b", "\\belif\\b", "\\bwhile\\b", "\\bfor\\b", "\\breturn\\b", "\\bprint\\b", "\\bimport\\b", @@ -148,24 +166,20 @@ static QVector pythonHighlightingRules() for (const QString &pattern : keywordPatterns) { rule.pattern = QRegularExpression(pattern); - rule.format = keywordFormat; + rule.format = Keyword; highlightingRules.append(rule); } - QTextCharFormat stringFormat; - stringFormat.setForeground(stringColor); rule.pattern = QRegularExpression("\".*?\""); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); rule.pattern = QRegularExpression("\'.*?\'"); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); - QTextCharFormat commentFormat; - commentFormat.setForeground(commentColor); rule.pattern = QRegularExpression("#[^\n]*"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); } @@ -179,36 +193,26 @@ static QVector csharpHighlightingRules() HighlightingRule rule; - QTextCharFormat defaultFormat; - defaultFormat.setForeground(defaultColor); rule.pattern = QRegularExpression(".*"); - rule.format = defaultFormat; + rule.format = Default; highlightingRules.append(rule); // Function call highlighting - QTextCharFormat functionCallFormat; - functionCallFormat.setForeground(functionCallColor); rule.pattern = QRegularExpression("\\b(\\w+)\\s*(?=\\()"); - rule.format = functionCallFormat; + rule.format = FunctionCall; highlightingRules.append(rule); // Function definition highlighting - QTextCharFormat functionFormat; - functionFormat.setForeground(functionColor); rule.pattern = QRegularExpression("\\bvoid|int|double|string|bool\\s+(\\w+)\\s*(?=\\()"); - rule.format = functionFormat; + rule.format = Function; highlightingRules.append(rule); // Number highlighting - QTextCharFormat numberFormat; - numberFormat.setForeground(numberColor); rule.pattern = QRegularExpression("\\b[0-9]*\\.?[0-9]+\\b"); - rule.format = numberFormat; + rule.format = Number; highlightingRules.append(rule); // Keyword highlighting - QTextCharFormat keywordFormat; - keywordFormat.setForeground(keywordColor); QStringList keywordPatterns = { "\\bvoid\\b", "\\bint\\b", "\\bdouble\\b", "\\bstring\\b", "\\bbool\\b", "\\bclass\\b", "\\bif\\b", "\\belse\\b", "\\bwhile\\b", "\\bfor\\b", @@ -220,27 +224,23 @@ static QVector csharpHighlightingRules() for (const QString &pattern : keywordPatterns) { rule.pattern = QRegularExpression(pattern); - rule.format = keywordFormat; + rule.format = Keyword; highlightingRules.append(rule); } // String highlighting - QTextCharFormat stringFormat; - stringFormat.setForeground(stringColor); rule.pattern = QRegularExpression("\".*?\""); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); // Single-line comment highlighting - QTextCharFormat commentFormat; - commentFormat.setForeground(commentColor); rule.pattern = QRegularExpression("//[^\n]*"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); // Multi-line comment highlighting rule.pattern = QRegularExpression("/\\*.*?\\*/"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); } return highlightingRules; @@ -253,32 +253,22 @@ static QVector cppHighlightingRules() HighlightingRule rule; - QTextCharFormat defaultFormat; - defaultFormat.setForeground(defaultColor); rule.pattern = QRegularExpression(".*"); - rule.format = defaultFormat; + rule.format = Default; highlightingRules.append(rule); - QTextCharFormat functionCallFormat; - functionCallFormat.setForeground(functionCallColor); rule.pattern = QRegularExpression("\\b(\\w+)\\s*(?=\\()"); - rule.format = functionCallFormat; + rule.format = FunctionCall; highlightingRules.append(rule); - QTextCharFormat functionFormat; - functionFormat.setForeground(functionColor); rule.pattern = QRegularExpression("\\b[a-zA-Z_][a-zA-Z0-9_]*\\s+(\\w+)\\s*\\("); - rule.format = functionFormat; + rule.format = Function; highlightingRules.append(rule); - QTextCharFormat numberFormat; - numberFormat.setForeground(numberColor); rule.pattern = QRegularExpression("\\b[0-9]*\\.?[0-9]+\\b"); - rule.format = numberFormat; + rule.format = Number; highlightingRules.append(rule); - QTextCharFormat keywordFormat; - keywordFormat.setForeground(keywordColor); QStringList keywordPatterns = { "\\bauto\\b", "\\bbool\\b", "\\bbreak\\b", "\\bcase\\b", "\\bcatch\\b", "\\bchar\\b", "\\bclass\\b", "\\bconst\\b", "\\bconstexpr\\b", "\\bcontinue\\b", @@ -297,34 +287,28 @@ static QVector cppHighlightingRules() for (const QString &pattern : keywordPatterns) { rule.pattern = QRegularExpression(pattern); - rule.format = keywordFormat; + rule.format = Keyword; highlightingRules.append(rule); } - QTextCharFormat stringFormat; - stringFormat.setForeground(stringColor); rule.pattern = QRegularExpression("\".*?\""); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); rule.pattern = QRegularExpression("\'.*?\'"); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); - QTextCharFormat commentFormat; - commentFormat.setForeground(commentColor); rule.pattern = QRegularExpression("//[^\n]*"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); rule.pattern = QRegularExpression("/\\*.*?\\*/"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); - QTextCharFormat preprocessorFormat; - preprocessorFormat.setForeground(preprocessorColor); rule.pattern = QRegularExpression("#(?:include|define|undef|ifdef|ifndef|if|else|elif|endif|error|pragma)\\b.*"); - rule.format = preprocessorFormat; + rule.format = Preprocessor; highlightingRules.append(rule); } return highlightingRules; @@ -337,32 +321,22 @@ static QVector typescriptHighlightingRules() HighlightingRule rule; - QTextCharFormat defaultFormat; - defaultFormat.setForeground(defaultColor); rule.pattern = QRegularExpression(".*"); - rule.format = defaultFormat; + rule.format = Default; highlightingRules.append(rule); - QTextCharFormat functionCallFormat; - functionCallFormat.setForeground(functionCallColor); rule.pattern = QRegularExpression("\\b(\\w+)\\s*(?=\\()"); - rule.format = functionCallFormat; + rule.format = FunctionCall; highlightingRules.append(rule); - QTextCharFormat functionFormat; - functionFormat.setForeground(functionColor); rule.pattern = QRegularExpression("\\bfunction\\s+(\\w+)\\b"); - rule.format = functionFormat; + rule.format = Function; highlightingRules.append(rule); - QTextCharFormat numberFormat; - numberFormat.setForeground(numberColor); rule.pattern = QRegularExpression("\\b[0-9]*\\.?[0-9]+\\b"); - rule.format = numberFormat; + rule.format = Number; highlightingRules.append(rule); - QTextCharFormat keywordFormat; - keywordFormat.setForeground(keywordColor); QStringList keywordPatterns = { "\\bfunction\\b", "\\bvar\\b", "\\blet\\b", "\\bconst\\b", "\\bif\\b", "\\belse\\b", "\\bfor\\b", "\\bwhile\\b", "\\breturn\\b", "\\btry\\b", "\\bcatch\\b", "\\bfinally\\b", @@ -377,12 +351,10 @@ static QVector typescriptHighlightingRules() for (const QString &pattern : keywordPatterns) { rule.pattern = QRegularExpression(pattern); - rule.format = keywordFormat; + rule.format = Keyword; highlightingRules.append(rule); } - QTextCharFormat typeFormat; - typeFormat.setForeground(typeColor); QStringList typePatterns = { "\\bstring\\b", "\\bnumber\\b", "\\bboolean\\b", "\\bany\\b", "\\bvoid\\b", "\\bnever\\b", "\\bunknown\\b", "\\bObject\\b", "\\bArray\\b" @@ -390,30 +362,24 @@ static QVector typescriptHighlightingRules() for (const QString &pattern : typePatterns) { rule.pattern = QRegularExpression(pattern); - rule.format = typeFormat; + rule.format = Type; highlightingRules.append(rule); } - QTextCharFormat stringFormat; - stringFormat.setForeground(stringColor); rule.pattern = QRegularExpression("\".*?\"|'.*?'|`.*?`"); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); - QTextCharFormat commentFormat; - commentFormat.setForeground(commentColor); rule.pattern = QRegularExpression("//[^\n]*"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); rule.pattern = QRegularExpression("/\\*.*?\\*/"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); - QTextCharFormat arrowFormat; - arrowFormat.setForeground(arrowColor); rule.pattern = QRegularExpression("=>"); - rule.format = arrowFormat; + rule.format = Arrow; highlightingRules.append(rule); } @@ -427,32 +393,22 @@ static QVector javaHighlightingRules() HighlightingRule rule; - QTextCharFormat defaultFormat; - defaultFormat.setForeground(defaultColor); rule.pattern = QRegularExpression(".*"); - rule.format = defaultFormat; + rule.format = Default; highlightingRules.append(rule); - QTextCharFormat functionCallFormat; - functionCallFormat.setForeground(functionCallColor); rule.pattern = QRegularExpression("\\b(\\w+)\\s*(?=\\()"); - rule.format = functionCallFormat; + rule.format = FunctionCall; highlightingRules.append(rule); - QTextCharFormat functionFormat; - functionFormat.setForeground(functionColor); rule.pattern = QRegularExpression("\\bvoid\\s+(\\w+)\\b"); - rule.format = functionFormat; + rule.format = Function; highlightingRules.append(rule); - QTextCharFormat numberFormat; - numberFormat.setForeground(numberColor); rule.pattern = QRegularExpression("\\b[0-9]*\\.?[0-9]+\\b"); - rule.format = numberFormat; + rule.format = Number; highlightingRules.append(rule); - QTextCharFormat keywordFormat; - keywordFormat.setForeground(keywordColor); QStringList keywordPatterns = { "\\bpublic\\b", "\\bprivate\\b", "\\bprotected\\b", "\\bstatic\\b", "\\bfinal\\b", "\\bclass\\b", "\\bif\\b", "\\belse\\b", "\\bwhile\\b", "\\bfor\\b", @@ -468,28 +424,24 @@ static QVector javaHighlightingRules() for (const QString &pattern : keywordPatterns) { rule.pattern = QRegularExpression(pattern); - rule.format = keywordFormat; + rule.format = Keyword; highlightingRules.append(rule); } - QTextCharFormat stringFormat; - stringFormat.setForeground(stringColor); rule.pattern = QRegularExpression("\".*?\""); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); rule.pattern = QRegularExpression("\'.*?\'"); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); - QTextCharFormat commentFormat; - commentFormat.setForeground(commentColor); rule.pattern = QRegularExpression("//[^\n]*"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); rule.pattern = QRegularExpression("/\\*.*?\\*/"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); } return highlightingRules; @@ -502,32 +454,22 @@ static QVector goHighlightingRules() HighlightingRule rule; - QTextCharFormat defaultFormat; - defaultFormat.setForeground(defaultColor); rule.pattern = QRegularExpression(".*"); - rule.format = defaultFormat; + rule.format = Default; highlightingRules.append(rule); - QTextCharFormat functionCallFormat; - functionCallFormat.setForeground(functionCallColor); rule.pattern = QRegularExpression("\\b(\\w+)\\s*(?=\\()"); - rule.format = functionCallFormat; + rule.format = FunctionCall; highlightingRules.append(rule); - QTextCharFormat functionFormat; - functionFormat.setForeground(functionColor); rule.pattern = QRegularExpression("\\bfunc\\s+(\\w+)\\b"); - rule.format = functionFormat; + rule.format = Function; highlightingRules.append(rule); - QTextCharFormat numberFormat; - numberFormat.setForeground(numberColor); rule.pattern = QRegularExpression("\\b[0-9]*\\.?[0-9]+\\b"); - rule.format = numberFormat; + rule.format = Number; highlightingRules.append(rule); - QTextCharFormat keywordFormat; - keywordFormat.setForeground(keywordColor); QStringList keywordPatterns = { "\\bfunc\\b", "\\bpackage\\b", "\\bimport\\b", "\\bvar\\b", "\\bconst\\b", "\\btype\\b", "\\bstruct\\b", "\\binterface\\b", "\\bfor\\b", "\\bif\\b", @@ -538,28 +480,24 @@ static QVector goHighlightingRules() for (const QString &pattern : keywordPatterns) { rule.pattern = QRegularExpression(pattern); - rule.format = keywordFormat; + rule.format = Keyword; highlightingRules.append(rule); } - QTextCharFormat stringFormat; - stringFormat.setForeground(stringColor); rule.pattern = QRegularExpression("\".*?\""); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); rule.pattern = QRegularExpression("`.*?`"); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); - QTextCharFormat commentFormat; - commentFormat.setForeground(commentColor); rule.pattern = QRegularExpression("//[^\n]*"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); rule.pattern = QRegularExpression("/\\*.*?\\*/"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); } @@ -573,32 +511,24 @@ static QVector bashHighlightingRules() HighlightingRule rule; - QTextCharFormat defaultFormat; - defaultFormat.setForeground(defaultColor); rule.pattern = QRegularExpression(".*"); - rule.format = defaultFormat; + rule.format = Default; highlightingRules.append(rule); - QTextCharFormat commandFormat; - commandFormat.setForeground(commandColor); QStringList commandPatterns = { "\\b(grep|awk|sed|ls|cat|echo|rm|mkdir|cp|break|alias|eval|cd|exec|head|tail|strings|printf|touch|mv|chmod)\\b" }; for (const QString &pattern : commandPatterns) { rule.pattern = QRegularExpression(pattern); - rule.format = commandFormat; + rule.format = Command; highlightingRules.append(rule); } - QTextCharFormat numberFormat; - numberFormat.setForeground(numberColor); rule.pattern = QRegularExpression("\\b[0-9]*\\.?[0-9]+\\b"); - rule.format = numberFormat; + rule.format = Number; highlightingRules.append(rule); - QTextCharFormat keywordFormat; - keywordFormat.setForeground(keywordColor); QStringList keywordPatterns = { "\\bif\\b", "\\bthen\\b", "\\belse\\b", "\\bfi\\b", "\\bfor\\b", "\\bin\\b", "\\bdo\\b", "\\bdone\\b", "\\bwhile\\b", "\\buntil\\b", @@ -609,30 +539,24 @@ static QVector bashHighlightingRules() for (const QString &pattern : keywordPatterns) { rule.pattern = QRegularExpression(pattern); - rule.format = keywordFormat; + rule.format = Keyword; highlightingRules.append(rule); } - QTextCharFormat stringFormat; - stringFormat.setForeground(stringColor); rule.pattern = QRegularExpression("\".*?\""); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); rule.pattern = QRegularExpression("\'.*?\'"); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); - QTextCharFormat variableFormat; - variableFormat.setForeground(variableColor); rule.pattern = QRegularExpression("\\$(\\w+|\\{[^}]+\\})"); - rule.format = variableFormat; + rule.format = Variable; highlightingRules.append(rule); - QTextCharFormat commentFormat; - commentFormat.setForeground(commentColor); rule.pattern = QRegularExpression("#[^\n]*"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); } @@ -646,22 +570,16 @@ static QVector latexHighlightingRules() HighlightingRule rule; - QTextCharFormat defaultFormat; - defaultFormat.setForeground(defaultColor); rule.pattern = QRegularExpression(".*"); - rule.format = defaultFormat; + rule.format = Default; highlightingRules.append(rule); - QTextCharFormat commandFormat; - commandFormat.setForeground(commandColor); // commandColor needs to be set to your liking rule.pattern = QRegularExpression("\\\\[A-Za-z]+"); // Pattern for LaTeX commands - rule.format = commandFormat; + rule.format = Command; highlightingRules.append(rule); - QTextCharFormat commentFormat; - commentFormat.setForeground(commentColor); // commentColor needs to be set to your liking rule.pattern = QRegularExpression("%[^\n]*"); // Pattern for LaTeX comments - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); } return highlightingRules; @@ -674,40 +592,28 @@ static QVector htmlHighlightingRules() HighlightingRule rule; - QTextCharFormat defaultFormat; - defaultFormat.setForeground(defaultColor); rule.pattern = QRegularExpression(".*"); - rule.format = defaultFormat; + rule.format = Default; highlightingRules.append(rule); - QTextCharFormat attributeNameFormat; - attributeNameFormat.setForeground(attributeNameColor); rule.pattern = QRegularExpression("\\b(\\w+)\\s*="); - rule.format = attributeNameFormat; + rule.format = AttributeName; highlightingRules.append(rule); - QTextCharFormat attributeValueFormat; - attributeValueFormat.setForeground(attributeValueColor); rule.pattern = QRegularExpression("\".*?\"|'.*?'"); - rule.format = attributeValueFormat; + rule.format = AttributeValue; highlightingRules.append(rule); - QTextCharFormat commentFormat; - commentFormat.setForeground(commentColor); rule.pattern = QRegularExpression(""); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); - QTextCharFormat specialCharacterFormat; - specialCharacterFormat.setForeground(specialCharacterColor); rule.pattern = QRegularExpression("&[a-zA-Z0-9#]*;"); - rule.format = specialCharacterFormat; + rule.format = SpecialCharacter; highlightingRules.append(rule); - QTextCharFormat doctypeFormat; - doctypeFormat.setForeground(doctypeColor); rule.pattern = QRegularExpression(""); - rule.format = doctypeFormat; + rule.format = DocType; highlightingRules.append(rule); } return highlightingRules; @@ -720,32 +626,22 @@ static QVector phpHighlightingRules() HighlightingRule rule; - QTextCharFormat defaultFormat; - defaultFormat.setForeground(defaultColor); rule.pattern = QRegularExpression(".*"); - rule.format = defaultFormat; + rule.format = Default; highlightingRules.append(rule); - QTextCharFormat functionCallFormat; - functionCallFormat.setForeground(functionCallColor); rule.pattern = QRegularExpression("\\b(\\w+)\\s*(?=\\()"); - rule.format = functionCallFormat; + rule.format = FunctionCall; highlightingRules.append(rule); - QTextCharFormat functionFormat; - functionFormat.setForeground(functionColor); rule.pattern = QRegularExpression("\\bfunction\\s+(\\w+)\\b"); - rule.format = functionFormat; + rule.format = Function; highlightingRules.append(rule); - QTextCharFormat numberFormat; - numberFormat.setForeground(numberColor); rule.pattern = QRegularExpression("\\b[0-9]*\\.?[0-9]+\\b"); - rule.format = numberFormat; + rule.format = Number; highlightingRules.append(rule); - QTextCharFormat keywordFormat; - keywordFormat.setForeground(keywordColor); QStringList keywordPatterns = { "\\bif\\b", "\\belse\\b", "\\belseif\\b", "\\bwhile\\b", "\\bfor\\b", "\\bforeach\\b", "\\breturn\\b", "\\bprint\\b", "\\binclude\\b", "\\brequire\\b", @@ -758,28 +654,24 @@ static QVector phpHighlightingRules() for (const QString &pattern : keywordPatterns) { rule.pattern = QRegularExpression(pattern); - rule.format = keywordFormat; + rule.format = Keyword; highlightingRules.append(rule); } - QTextCharFormat stringFormat; - stringFormat.setForeground(stringColor); rule.pattern = QRegularExpression("\".*?\""); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); rule.pattern = QRegularExpression("\'.*?\'"); - rule.format = stringFormat; + rule.format = String; highlightingRules.append(rule); - QTextCharFormat commentFormat; - commentFormat.setForeground(commentColor); rule.pattern = QRegularExpression("//[^\n]*"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); rule.pattern = QRegularExpression("/\\*.*?\\*/"); - rule.format = commentFormat; + rule.format = Comment; highlightingRules.append(rule); } return highlightingRules; @@ -793,30 +685,23 @@ static QVector jsonHighlightingRules() HighlightingRule rule; - QTextCharFormat defaultFormat; - defaultFormat.setForeground(defaultColor); rule.pattern = QRegularExpression(".*"); - rule.format = defaultFormat; + rule.format = Default; highlightingRules.append(rule); // Key string rule - QTextCharFormat keyFormat; - keyFormat.setForeground(keyColor); // Assuming keyColor is defined rule.pattern = QRegularExpression("\".*?\":"); // keys are typically in the "key": format - rule.format = keyFormat; + rule.format = Key; highlightingRules.append(rule); // Value string rule - QTextCharFormat valueFormat; - valueFormat.setForeground(valueColor); // Assuming valueColor is defined rule.pattern = QRegularExpression(":\\s*(\".*?\")"); // values are typically in the : "value" format - rule.format = valueFormat; + rule.format = Value; highlightingRules.append(rule); } return highlightingRules; } - SyntaxHighlighter::SyntaxHighlighter(QObject *parent) : QSyntaxHighlighter(parent) { @@ -871,7 +756,9 @@ void SyntaxHighlighter::highlightBlock(const QString &text) QRegularExpressionMatch match = matchIterator.next(); int startIndex = match.capturedStart(); int length = match.capturedLength(); - setFormat(startIndex, length, rule.format); + QTextCharFormat format; + format.setForeground(formatToColor(rule.format, m_codeColors)); + setFormat(startIndex, length, format); } } } @@ -948,6 +835,17 @@ void ChatViewTextProcessor::setFontPixelSize(qreal sz) handleTextChanged(); } +CodeColors ChatViewTextProcessor::codeColors() const +{ + return m_syntaxHighlighter->codeColors(); +} + +void ChatViewTextProcessor::setCodeColors(const CodeColors &colors) +{ + m_syntaxHighlighter->setCodeColors(colors); + emit codeColorsChanged(); +} + void traverseDocument(QTextDocument *doc, QTextFrame *frame) { QTextFrame *rootFrame = frame ? frame : doc->rootFrame(); @@ -1001,6 +899,8 @@ void ChatViewTextProcessor::handleTextChanged() QTextCursor cursor(doc); QString invisibleCharacter = QString(QChar(0xFEFF)); cursor.insertText(invisibleCharacter, QTextCharFormat()); + + m_syntaxHighlighter->rehighlight(); m_isProcessingText = false; } @@ -1014,7 +914,7 @@ void ChatViewTextProcessor::handleCodeBlocks() textFormat.setForeground(QColor("white")); QTextFrameFormat frameFormatBase; - frameFormatBase.setBackground(QColor("black")); + frameFormatBase.setBackground(codeColors().backgroundColor); QTextTableFormat tableFormat; tableFormat.setMargin(0); @@ -1026,33 +926,33 @@ void ChatViewTextProcessor::handleCodeBlocks() tableFormat.setColumnWidthConstraints(constraints); QTextTableFormat headerTableFormat; - headerTableFormat.setBackground(m_headerColor); + headerTableFormat.setBackground(codeColors().headerColor); headerTableFormat.setPadding(0); headerTableFormat.setBorder(0); headerTableFormat.setBorderCollapse(true); - headerTableFormat.setTopMargin(15); - headerTableFormat.setBottomMargin(15); - headerTableFormat.setLeftMargin(30); - headerTableFormat.setRightMargin(30); + headerTableFormat.setTopMargin(10); + headerTableFormat.setBottomMargin(10); + headerTableFormat.setLeftMargin(15); + headerTableFormat.setRightMargin(15); QList headerConstraints; headerConstraints << QTextLength(QTextLength::PercentageLength, 80); headerConstraints << QTextLength(QTextLength::PercentageLength, 20); headerTableFormat.setColumnWidthConstraints(headerConstraints); QTextTableFormat codeBlockTableFormat; - codeBlockTableFormat.setBackground(QColor("black")); + codeBlockTableFormat.setBackground(codeColors().backgroundColor); codeBlockTableFormat.setPadding(0); codeBlockTableFormat.setBorder(0); codeBlockTableFormat.setBorderCollapse(true); - codeBlockTableFormat.setTopMargin(30); - codeBlockTableFormat.setBottomMargin(30); - codeBlockTableFormat.setLeftMargin(30); - codeBlockTableFormat.setRightMargin(30); + codeBlockTableFormat.setTopMargin(15); + codeBlockTableFormat.setBottomMargin(15); + codeBlockTableFormat.setLeftMargin(15); + codeBlockTableFormat.setRightMargin(15); codeBlockTableFormat.setColumnWidthConstraints(constraints); QTextImageFormat copyImageFormat; - copyImageFormat.setWidth(30); - copyImageFormat.setHeight(30); + copyImageFormat.setWidth(24); + copyImageFormat.setHeight(24); copyImageFormat.setName("qrc:/gpt4all/icons/copy.svg"); // Regex for code blocks @@ -1126,10 +1026,17 @@ void ChatViewTextProcessor::handleCodeBlocks() newCopy.startPos = copyCursor.position(); newCopy.endPos = newCopy.startPos + 1; newCopies.append(newCopy); - QTextBlockFormat blockFormat; - blockFormat.setAlignment(Qt::AlignRight); - copyCursor.setBlockFormat(blockFormat); - copyCursor.insertImage(copyImageFormat, QTextFrameFormat::FloatRight); +// FIXME: There are two reasons this is commented out. Odd drawing behavior is seen when this is added +// and one selects with the mouse the code language in a code block. The other reason is the code that +// tries to do a hit test for the image is just very broken and buggy and does not always work. So I'm +// disabling this code and included functionality for v3.0.0 until I can figure out how to make this much +// less buggy +#if 0 +// QTextBlockFormat blockFormat; +// blockFormat.setAlignment(Qt::AlignRight); +// copyCursor.setBlockFormat(blockFormat); +// copyCursor.insertImage(copyImageFormat, QTextFrameFormat::FloatRight); +#endif } QTextTableCell codeCell = table->cellAt(codeLanguage.isEmpty() ? 0 : 1, 0); @@ -1138,7 +1045,7 @@ void ChatViewTextProcessor::handleCodeBlocks() QTextTableCell code = codeTable->cellAt(0, 0); QTextCharFormat codeBlockCharFormat; - codeBlockCharFormat.setForeground(defaultColor); + codeBlockCharFormat.setForeground(codeColors().defaultColor); QFont monospaceFont("Courier"); monospaceFont.setPointSize(m_fontPixelSize); diff --git a/gpt4all-chat/chatviewtextprocessor.h b/gpt4all-chat/chatviewtextprocessor.h index 60207f44..33ddbfd4 100644 --- a/gpt4all-chat/chatviewtextprocessor.h +++ b/gpt4all-chat/chatviewtextprocessor.h @@ -16,12 +16,57 @@ class QPainter; class QTextDocument; class QTextFormat; +struct CodeColors { + Q_GADGET + Q_PROPERTY(QColor defaultColor MEMBER defaultColor) + Q_PROPERTY(QColor keywordColor MEMBER keywordColor) + Q_PROPERTY(QColor functionColor MEMBER functionColor) + Q_PROPERTY(QColor functionCallColor MEMBER functionCallColor) + Q_PROPERTY(QColor commentColor MEMBER commentColor) + Q_PROPERTY(QColor stringColor MEMBER stringColor) + Q_PROPERTY(QColor numberColor MEMBER numberColor) + Q_PROPERTY(QColor headerColor MEMBER headerColor) + Q_PROPERTY(QColor backgroundColor MEMBER backgroundColor) + +public: + QColor defaultColor; + QColor keywordColor; + QColor functionColor; + QColor functionCallColor; + QColor commentColor; + QColor stringColor; + QColor numberColor; + QColor headerColor; + QColor backgroundColor; + + QColor preprocessorColor = keywordColor; + QColor typeColor = numberColor; + QColor arrowColor = functionColor; + QColor commandColor = functionCallColor; + QColor variableColor = numberColor; + QColor keyColor = functionColor; + QColor valueColor = stringColor; + QColor parameterColor = stringColor; + QColor attributeNameColor = numberColor; + QColor attributeValueColor = stringColor; + QColor specialCharacterColor = functionColor; + QColor doctypeColor = commentColor; +}; + +Q_DECLARE_METATYPE(CodeColors) + class SyntaxHighlighter : public QSyntaxHighlighter { Q_OBJECT public: SyntaxHighlighter(QObject *parent); ~SyntaxHighlighter(); void highlightBlock(const QString &text) override; + + CodeColors codeColors() const { return m_codeColors; } + void setCodeColors(const CodeColors &colors) { m_codeColors = colors; } + +private: + CodeColors m_codeColors; }; struct ContextLink { @@ -43,6 +88,7 @@ class ChatViewTextProcessor : public QObject 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()) + Q_PROPERTY(CodeColors codeColors READ codeColors WRITE setCodeColors NOTIFY codeColorsChanged()) QML_ELEMENT public: explicit ChatViewTextProcessor(QObject *parent = nullptr); @@ -50,9 +96,6 @@ public: QQuickTextDocument* textDocument() const; void setTextDocument(QQuickTextDocument* textDocument); - Q_INVOKABLE void setLinkColor(const QColor &c) { m_linkColor = c; } - Q_INVOKABLE void setHeaderColor(const QColor &c) { m_headerColor = c; } - Q_INVOKABLE bool tryCopyAtPosition(int position) const; bool shouldProcessText() const; @@ -61,10 +104,14 @@ public: qreal fontPixelSize() const; void setFontPixelSize(qreal b); + CodeColors codeColors() const; + void setCodeColors(const CodeColors &colors); + Q_SIGNALS: void textDocumentChanged(); void shouldProcessTextChanged(); void fontPixelSizeChanged(); + void codeColorsChanged(); private Q_SLOTS: void handleTextChanged(); @@ -76,8 +123,6 @@ private: SyntaxHighlighter *m_syntaxHighlighter; QVector m_links; QVector m_copies; - QColor m_linkColor; - QColor m_headerColor; bool m_shouldProcessText = false; bool m_isProcessingText = false; qreal m_fontPixelSize; diff --git a/gpt4all-chat/mysettings.cpp b/gpt4all-chat/mysettings.cpp index 9b6badef..6ea6ae43 100644 --- a/gpt4all-chat/mysettings.cpp +++ b/gpt4all-chat/mysettings.cpp @@ -41,7 +41,7 @@ static const QVariantMap basicDefaults { { "saveChatsContext", false }, { "serverChat", false }, { "userDefaultModel", "Application default" }, - { "localdocs/chunkSize", 256 }, + { "localdocs/chunkSize", 512 }, { "localdocs/retrievalSize", 3 }, { "localdocs/showReferences", true }, { "localdocs/fileExtensions", QStringList { "txt", "pdf", "md", "rst" } }, diff --git a/gpt4all-chat/qml/ChatView.qml b/gpt4all-chat/qml/ChatView.qml index 8a9c268a..8b423864 100644 --- a/gpt4all-chat/qml/ChatView.qml +++ b/gpt4all-chat/qml/ChatView.qml @@ -949,13 +949,35 @@ Rectangle { ChatViewTextProcessor { id: textProcessor - fontPixelSize: myTextArea.font.pixelSize + } + + function resetChatViewTextProcessor() { + textProcessor.fontPixelSize = myTextArea.font.pixelSize + textProcessor.codeColors.defaultColor = theme.codeDefaultColor + textProcessor.codeColors.keywordColor = theme.codeKeywordColor + textProcessor.codeColors.functionColor = theme.codeFunctionColor + textProcessor.codeColors.functionCallColor = theme.codeFunctionCallColor + textProcessor.codeColors.commentColor = theme.codeCommentColor + textProcessor.codeColors.stringColor = theme.codeStringColor + textProcessor.codeColors.numberColor = theme.codeNumberColor + textProcessor.codeColors.headerColor = theme.codeHeaderColor + textProcessor.codeColors.backgroundColor = theme.codeBackgroundColor + textProcessor.textDocument = textDocument + myTextArea.text = value } Component.onCompleted: { - textProcessor.setLinkColor(theme.linkColor); - textProcessor.setHeaderColor(name === qsTr("Response: ") ? theme.darkContrast : theme.lightContrast); - textProcessor.textDocument = textDocument + resetChatViewTextProcessor(); + } + + Connections { + target: MySettings + function onFontSizeChanged() { + myTextArea.resetChatViewTextProcessor(); + } + function onChatThemeChanged() { + myTextArea.resetChatViewTextProcessor(); + } } Accessible.role: Accessible.Paragraph @@ -1463,7 +1485,7 @@ Rectangle { id: conversationTrayButton anchors.bottom: textInputView.top anchors.horizontalCenter: textInputView.horizontalCenter - width: 30 + width: 40 height: 30 visible: chatModel.count && !currentChat.isServer && currentChat.isModelLoaded property bool isHovered: conversationTrayMouseAreaButton.containsMouse @@ -1474,13 +1496,14 @@ Rectangle { } Text { id: conversationTrayTextButton - anchors.horizontalCenter: parent.horizontalCenter + anchors.centerIn: parent horizontalAlignment: Qt.AlignHCenter leftPadding: 5 rightPadding: 5 text: "\u00B7\u00B7\u00B7" color: theme.textColor - font.pixelSize: 20 // fixed size + font.pixelSize: 30 // fixed size + font.bold: true } } @@ -1670,8 +1693,8 @@ Rectangle { anchors.right: textInputView.right anchors.verticalCenter: textInputView.verticalCenter anchors.rightMargin: 15 - imageWidth: theme.fontSizeLarger - imageHeight: theme.fontSizeLarger + imageWidth: theme.fontSizeLargest + imageHeight: theme.fontSizeLargest visible: !currentChat.isServer && ModelList.selectableModels.count !== 0 enabled: !currentChat.responseInProgress source: "qrc:/gpt4all/icons/send_message.svg" diff --git a/gpt4all-chat/qml/Theme.qml b/gpt4all-chat/qml/Theme.qml index 880d674f..c558e348 100644 --- a/gpt4all-chat/qml/Theme.qml +++ b/gpt4all-chat/qml/Theme.qml @@ -824,8 +824,6 @@ QtObject { // lighter contrast property color mutedLighterTextColor: { switch (MySettings.chatTheme) { -// case "LegacyDark": -// case "Dark": default: return gray300; } @@ -834,8 +832,6 @@ QtObject { // light contrast property color mutedLightTextColor: { switch (MySettings.chatTheme) { -// case "LegacyDark": -// case "Dark": default: return gray400; } @@ -1069,6 +1065,95 @@ QtObject { } } + property color codeDefaultColor: { + switch (MySettings.chatTheme) { + case "LegacyDark": + case "Dark": + default: + return textColor; + } + } + + property color codeKeywordColor: { + switch (MySettings.chatTheme) { + case "LegacyDark": + case "Dark": + return "#2e95d3"; // blue + default: + return "#195273"; // dark blue + } + } + + property color codeFunctionColor: { + switch (MySettings.chatTheme) { + case "LegacyDark": + case "Dark": + return"#f22c3d"; // red + default: + return"#7d1721"; // dark red + } + } + + property color codeFunctionCallColor: { + switch (MySettings.chatTheme) { + case "LegacyDark": + case "Dark": + return "#e9950c"; // orange + default: + return "#815207"; // dark orange + } + } + + property color codeCommentColor: { + switch (MySettings.chatTheme) { + case "LegacyDark": + case "Dark": + return "#808080"; // gray + default: + return "#474747"; // dark gray + } + } + + property color codeStringColor: { + switch (MySettings.chatTheme) { + case "LegacyDark": + case "Dark": + return "#00a37d"; // green + default: + return "#004a39"; // dark green + } + } + + property color codeNumberColor: { + switch (MySettings.chatTheme) { + case "LegacyDark": + case "Dark": + return "#df3079"; // fuchsia + default: + return "#761942"; // dark fuchsia + } + } + + property color codeHeaderColor: { + switch (MySettings.chatTheme) { + case "LegacyDark": + case "Dark": + return containerBackground; + default: + return green50; + } + } + + property color codeBackgroundColor: { + switch (MySettings.chatTheme) { + case "LegacyDark": + case "Dark": + return controlBackground; + default: + return gray100; + } + } + property real fontScale: MySettings.fontSize === "Small" ? 1 : MySettings.fontSize === "Medium" ? 1.3 : /* "Large" */ 1.8