Git commit a646c4c1a85859c2aaf342bff7eaeeaa8891de0c by Benson Muite, on behalf of Omar Tamer. Committed on 20/09/2026 at 14:29. Pushed by kbkmde into branch 'master'.
Feature: Add named-color support to color commands M +32 -0 doc/glossary.docbook M +4 -2 doc/programming-reference.docbook M +2 -0 src/CMakeLists.txt A +68 -0 src/color.cpp * A +22 -0 src/color.h * M +14 -0 src/highlighter.cpp M +1 -0 src/highlighter.h M +1 -0 src/inspector.cpp M +54 -7 src/interpreter/executer.cpp M +2 -0 src/interpreter/executer.h M +2 -1 src/interpreter/token.h The files marked with a * at the end have a non valid license. Please read: https://community.kde.org/Policies/Licensing_Policy and use the headers which are listed at that page. https://invent.kde.org/education/kturtle/-/commit/a646c4c1a85859c2aaf342bff7eaeeaa8891de0c diff --git a/doc/glossary.docbook b/doc/glossary.docbook index c6a1ed6..301bd91 100644 --- a/doc/glossary.docbook +++ b/doc/glossary.docbook @@ -80,6 +80,11 @@ penup <entry>Not much to say about (text) strings either, except that they always start and end with the double quotes (").</entry> </row> <row> +<entry>named-colors</entry> +<entry>depends on color</entry> +<entry><glossterm linkend="named-colors">Named-colors</glossterm> will have a background color identical to them.</entry> +</row> +<row> <entry>numbers</entry> <entry>dark red</entry> <entry>Numbers, well not much to say about them.</entry> @@ -152,6 +157,33 @@ penup <para>Two commands need an RGB combination as input: these commands are <userinput>canvascolor</userinput> and <userinput>pencolor</userinput>.</para></glossdef> </glossentry> +<glossentry id="named-colors"> +<glossterm>Named-colors (color strings)</glossterm> +<glossdef><para>In addition to RGB combinations, you can use named-colors. Kturtle supports a group of named-colors, which are passed as strings to the command requiring a color. +<table frame="none"> +<title>Named-colors currently supported</title> +<tgroup cols="1" rowsep="1"> +<tbody> +<row><entry><userinput>"white"</userinput></entry></row> +<row><entry><userinput>"black"</userinput></entry></row> +<row><entry><userinput>"gray"</userinput></entry></row> +<row><entry><userinput>"grey"</userinput></entry></row> +<row><entry><userinput>"red"</userinput></entry></row> +<row><entry><userinput>"brown"</userinput></entry></row> +<row><entry><userinput>"orange"</userinput></entry></row> +<row><entry><userinput>"yellow"</userinput></entry></row> +<row><entry><userinput>"gold"</userinput></entry></row> +<row><entry><userinput>"green"</userinput></entry></row> +<row><entry><userinput>"blue"</userinput></entry></row> +<row><entry><userinput>"purple"</userinput></entry></row> +<row><entry><userinput>"pink"</userinput></entry></row> +</tbody> +</tgroup> +</table> +</para> +<para>Two commands can use a named-color as input: these commands are <userinput>canvascolor</userinput> and <userinput>pencolor</userinput>.</para></glossdef> +</glossentry> + <glossentry id="sprite"> <glossterm>sprite</glossterm> <glossdef><para>A sprite is a small picture that can be moved around the screen. Our beloved turtle, for instance, is a sprite. diff --git a/doc/programming-reference.docbook b/doc/programming-reference.docbook index 428112d..f23a094 100644 --- a/doc/programming-reference.docbook +++ b/doc/programming-reference.docbook @@ -363,7 +363,8 @@ Please note that <userinput>$A</userinput> and <userinput>$B</userinput> have to <varlistentry> <term>pencolor (pc)<indexterm><primary>pencolor (pc)</primary></indexterm></term> <listitem><para><screen>pencolor R,G,B</screen> - <userinput>pencolor</userinput> sets the color of the pen. <userinput>pencolor</userinput> takes an <glossterm linkend="rgb">RGB combination</glossterm> as input. <userinput>pencolor</userinput> can be abbreviated to <userinput>pc</userinput>.</para></listitem> + <screen>pencolor "color"</screen> + <userinput>pencolor</userinput> sets the color of the pen. <userinput>pencolor</userinput> takes an <glossterm linkend="rgb">RGB combination</glossterm> or a <glossterm linkend="named-colors">named-color</glossterm> as input. <userinput>pencolor</userinput> can be abbreviated to <userinput>pc</userinput>.</para></listitem> </varlistentry> </variablelist> </sect2> @@ -384,7 +385,8 @@ Please note that <userinput>$A</userinput> and <userinput>$B</userinput> have to <varlistentry> <term>canvascolor (cc)<indexterm><primary>canvascolor (cc)</primary></indexterm></term> <listitem><para><screen>canvascolor R,G,B</screen> - <userinput>canvascolor</userinput> set the color of the canvas. <userinput>canvascolor</userinput> takes an <glossterm linkend="rgb">RGB combination</glossterm> as input. <userinput>canvascolor</userinput> can be abbreviated to <userinput>cc</userinput>.</para></listitem> + <screen>canvascolor "color"</screen> + <userinput>canvascolor</userinput> set the color of the canvas. <userinput>canvascolor</userinput> takes an <glossterm linkend="rgb">RGB combination</glossterm> or <glossterm linkend="named-colors">named-color</glossterm> as input. <userinput>canvascolor</userinput> can be abbreviated to <userinput>cc</userinput>.</para></listitem> </varlistentry> </variablelist> </sect2> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 795a759..7096201 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,6 +14,8 @@ target_sources(kturtle PRIVATE kturtle.qrc canvas.cpp canvas.h + color.h + color.cpp colorpicker.cpp colorpicker.h console.cpp diff --git a/src/color.cpp b/src/color.cpp new file mode 100644 index 0000000..8d379a3 --- /dev/null +++ b/src/color.cpp @@ -0,0 +1,68 @@ +#include "color.h" + +QColor Color::colorString2RGB(QString colorString) +{ + // default to white + QColor color = QColorConstants::White; + if (isValidColorString(colorString)) { + return colorMap[colorString]; + } + return color; +} + +bool Color::isValidColorString(QString colorString) +{ + static bool colorMapInitialized = false; + if (!colorMapInitialized) { + colorMapInitialized = true; + initColorMap(); + } + + if (colorMap.contains(colorString)) { + return true; + } + return false; +} + +QColor Color::token2RGB(Token *token, ErrorList *errorList) +{ + QString colorString = token->look(); + colorString.removeFirst(); // removing quotes + colorString.removeLast(); + QColor color = QColorConstants::White; + if (isValidColorString(colorString)) { + return colorMap[colorString]; + } else { + errorList->addError(i18n("%1 is not a valid color.", colorString), *token, 20000 + Token::Color * 100 + 90); + } + return color; +} + +void Color::initColorMap() +{ + colorMap[i18n("white")] = QColorConstants::Svg::white; + + colorMap[i18n("black")] = QColorConstants::Svg::black; + + colorMap[i18n("grey")] = QColorConstants::Svg::gray; + + colorMap[i18n("gray")] = QColorConstants::Svg::gray; + + colorMap[i18n("red")] = QColorConstants::Svg::red; + + colorMap[i18n("brown")] = QColorConstants::Svg::brown; + + colorMap[i18n("orange")] = QColorConstants::Svg::orange; + + colorMap[i18n("yellow")] = QColorConstants::Svg::yellow; + + colorMap[i18n("gold")] = QColorConstants::Svg::gold; + + colorMap[i18n("green")] = QColorConstants::Svg::green; + + colorMap[i18n("blue")] = QColorConstants::Svg::blue; + + colorMap[i18n("purple")] = QColorConstants::Svg::purple; + + colorMap[i18n("pink")] = QColorConstants::Svg::pink; +} diff --git a/src/color.h b/src/color.h new file mode 100644 index 0000000..d39c87d --- /dev/null +++ b/src/color.h @@ -0,0 +1,22 @@ +#ifndef _COLOR_H_ +#define _COLOR_H_ + +#include <KLocalizedString> +#include <QColor> +#include <QMap> + +#include "interpreter/errormsg.h" +#include "interpreter/token.h" + +namespace Color +{ + +static QMap<QString, QColor> colorMap{}; + +void initColorMap(); +bool isValidColorString(QString colorString); +QColor colorString2RGB(QString colorString); +QColor token2RGB(Token *token, ErrorList *errorList); +} + +#endif diff --git a/src/highlighter.cpp b/src/highlighter.cpp index 6d66436..be7571c 100644 --- a/src/highlighter.cpp +++ b/src/highlighter.cpp @@ -5,6 +5,9 @@ */ #include "highlighter.h" +#include "color.h" + +#include <KLocalizedString> Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) @@ -80,6 +83,10 @@ Token *Highlighter::checkOrApplyHighlighting(const QString &text, int cursorInde QTextCharFormat *Highlighter::tokenToFormat(Token *token) { + QString look = token->look(); + look.removeFirst(); + look.removeLast(); + switch (token->category()) { case Token::VariableCategory: return &variableFormat; @@ -90,6 +97,13 @@ QTextCharFormat *Highlighter::tokenToFormat(Token *token) case Token::CommentCategory: return &commentFormat; case Token::StringCategory: + // qDebug() << look; + if (Color::isValidColorString(look)) { + QColor color = Color::colorString2RGB(look); + colorStringFormat.setBackground(color); + colorStringFormat.setForeground(color.lightness() >= 100 ? Qt::black : Qt::white); + return &colorStringFormat; + } return &stringFormat; case Token::ScopeCategory: return &scopeFormat; diff --git a/src/highlighter.h b/src/highlighter.h index 5b1bc0e..c210aec 100644 --- a/src/highlighter.h +++ b/src/highlighter.h @@ -47,6 +47,7 @@ private: QTextCharFormat trueFalseFormat; QTextCharFormat commentFormat; QTextCharFormat stringFormat; + QTextCharFormat colorStringFormat; QTextCharFormat numberFormat; QTextCharFormat scopeFormat; QTextCharFormat controllerCommandFormat; diff --git a/src/inspector.cpp b/src/inspector.cpp index 5b68281..9c453af 100644 --- a/src/inspector.cpp +++ b/src/inspector.cpp @@ -239,6 +239,7 @@ QTreeWidgetItem *Inspector::walkTree(TreeNode *node) QTextCharFormat *format = highlighter->tokenToFormat(node->token()); if (format) { result->setForeground(0, format->foreground()); + result->setBackground(0, format->background()); QFont font(QFontDatabase::systemFont(QFontDatabase::FixedFont)); font.setBold(format->font().bold()); result->setFont(0, font); diff --git a/src/interpreter/executer.cpp b/src/interpreter/executer.cpp index 51154a2..6db89da 100644 --- a/src/interpreter/executer.cpp +++ b/src/interpreter/executer.cpp @@ -8,10 +8,12 @@ // every aspect of it is slightly changed by Cies Breijs. #include "executer.h" +#include "../color.h" #include <errno.h> #include <math.h> +#include <QColor> #include <QDebug> #include <QRandomGenerator> #include <QTimer> // for wait @@ -529,7 +531,7 @@ void Executer::executeVariable(TreeNode *node) void Executer::executeFunctionCall(TreeNode *node) { // //qDebug() << "called"; - if (node->parent()->token()->type() == Token::Learn) { // in case we're defining a function + if (node->parent()->token()->type() == Token::Learn) { currentNode = node->parent(); executeCurrent = true; return; @@ -1098,21 +1100,66 @@ void Executer::executePenDown(TreeNode *node) return; Q_EMIT penDown(); } + +/* Color Functions */ + void Executer::executePenColor(TreeNode *node) { - // //qDebug() << "called"; - if (!checkParameterQuantity(node, 3, 20000 + Token::PenColor * 100 + 90) || !checkParameterType(node, Value::Number, 20000 + Token::PenColor * 100 + 91)) + uint nodeSize = node->childCount(); + bool hasRgbValues = false; + bool hasColorString = false; + + if (nodeSize == 3) { + hasRgbValues = + checkParameterQuantity(node, 3, 20000 + Token::PenColor * 100 + 90) && checkParameterType(node, Value::Number, 20000 + Token::PenColor * 100 + 90); + } else if (nodeSize == 1) { + hasColorString = + checkParameterQuantity(node, 1, 20000 + Token::PenColor * 100 + 90) && checkParameterType(node, Value::String, 20000 + Token::PenColor * 100 + 90); + } + + if (!hasColorString && !hasRgbValues) { + addError(i18n("The command %1 takes either a string or %2 numbers", node->token()->look(), 3), *node->token(), 20000 + Token::PenColor * 100 + 90); return; - Q_EMIT penColor(node->child(0)->value()->number(), node->child(1)->value()->number(), node->child(2)->value()->number()); + } + + // //qDebug() << "called"; + if (hasRgbValues) { + Q_EMIT penColor(node->child(0)->value()->number(), node->child(1)->value()->number(), node->child(2)->value()->number()); + } else if (hasColorString) { + QColor color = Color::token2RGB(node->child(0)->token(), errorList); + Q_EMIT penColor(color.red(), color.green(), color.blue()); + } } void Executer::executeCanvasColor(TreeNode *node) { + uint nodeSize = node->childCount(); + bool hasRgbValues = false; + bool hasColorString = false; + + if (nodeSize == 3) { + hasRgbValues = checkParameterQuantity(node, 3, 20000 + Token::CanvasColor * 100 + 90) + && checkParameterType(node, Value::Number, 20000 + Token::CanvasColor * 100 + 90); + } else if (nodeSize == 1) { + hasColorString = checkParameterQuantity(node, 1, 20000 + Token::CanvasColor * 100 + 90) + && checkParameterType(node, Value::String, 20000 + Token::CanvasColor * 100 + 90); + } + // //qDebug() << "called"; - if (!checkParameterQuantity(node, 3, 20000 + Token::CanvasColor * 100 + 90) - || !checkParameterType(node, Value::Number, 20000 + Token::CanvasColor * 100 + 91)) + if (!hasColorString && !hasRgbValues) { + addError(i18n("The command %1 takes either a string or %2 numbers", node->token()->look(), 3), *node->token(), 20000 + Token::PenColor * 100 + 90); return; - Q_EMIT canvasColor(node->child(0)->value()->number(), node->child(1)->value()->number(), node->child(2)->value()->number()); + } + + if (hasRgbValues) { + Q_EMIT canvasColor(node->child(0)->value()->number(), node->child(1)->value()->number(), node->child(2)->value()->number()); + } else if (hasColorString) { + QColor color = Color::token2RGB(node->child(0)->token(), errorList); + Q_EMIT canvasColor(color.red(), color.green(), color.blue()); + } } + +/* End Color Functions */ + void Executer::executeCanvasSize(TreeNode *node) { // //qDebug() << "called"; diff --git a/src/interpreter/executer.h b/src/interpreter/executer.h index f1b1878..087f31d 100644 --- a/src/interpreter/executer.h +++ b/src/interpreter/executer.h @@ -7,6 +7,7 @@ #ifndef _EXECUTER_H_ #define _EXECUTER_H_ +#include <QColor> #include <QHash> #include <QObject> #include <QStack> @@ -239,6 +240,7 @@ private: TreeNode *getParentOfTokenTypes(TreeNode *child, QList<int> *types); inline void printExe(); + QColor colorString2RGB(QString colorString); Q_SIGNALS: void currentlyExecuting(TreeNode *node); diff --git a/src/interpreter/token.h b/src/interpreter/token.h index b9dff9d..4b05ea4 100644 --- a/src/interpreter/token.h +++ b/src/interpreter/token.h @@ -132,7 +132,8 @@ public: Sqrt, Round, GetDirection, - Mod + Mod, + Color // END GENERATED token_type_h CODE };
