diff --git a/doc/downloads/index.js b/doc/downloads/index.js
index 8ff5ca6aa5..f2f6b0a492 100644
--- a/doc/downloads/index.js
+++ b/doc/downloads/index.js
@@ -37,9 +37,7 @@ var jsonData = { "versions": [
}
],
"changes": [
- { "change": "General: can now reload a file using Ctrl
+R
(see issue #2286)." },
- { "change": "Simulation Experiment view: can now customise the font size of the different bits of text in a graph panel (see issue #2271). Fixed a small GUI glitch on macOS (see issue #2277). Fixed an issue with reloading a SED-ML file / COMBINE archive potentially crashing OpenCOR (see issue #2290)." },
- { "change": "Third-party libraries: upgraded LLVM+Clang to version 9.0.1 (see issue #2269). Upgraded the SUNDIALS library to version 5.1.0 (see issue #2272). Upgraded libgit2 to version 0.28.4 (see issue #2280). Upgraded Mesa to version 19.3.2 (see issue #2281)." }
+ { "change": "CellML Text view: greatly reduced the time and memory required to do syntax highlighting (see issue #2284)." }
]
},
{ "major": 0, "minor": 5, "patch": 0, "day": 15, "month": 10, "year": 2016, "type": 0, "license": 1,
diff --git a/doc/downloads/previousSnapshots.js b/doc/downloads/previousSnapshots.js
index c00d4df4e9..e0ec998dbe 100644
--- a/doc/downloads/previousSnapshots.js
+++ b/doc/downloads/previousSnapshots.js
@@ -1,4 +1,28 @@
var jsonData = { "versions": [
+ { "major": 0, "minor": 0, "patch": 0, "day": 20, "month": 1, "year": 2020, "type": 2, "license": 2,
+ "platforms": [
+ { "name": "Windows", "supported": "Windows 10",
+ "files": [
+ { "extension": ".exe" }, { "extension": ".zip" }
+ ]
+ },
+ { "name": "Linux", "supported": "Ubuntu 18.04 LTS (Bionic Beaver) and later",
+ "files": [
+ { "extension": ".tar.gz" }
+ ]
+ },
+ { "name": "macOS", "supported": "macOS 10.12 (Sierra) and later",
+ "files": [
+ { "extension": ".pkg" }, { "extension": ".zip" }
+ ]
+ }
+ ],
+ "changes": [
+ { "change": "General: can now reload a file using Ctrl
+R
(see issue #2286)." },
+ { "change": "Simulation Experiment view: can now customise the font size of the different bits of text in a graph panel (see issue #2271). Fixed a small GUI glitch on macOS (see issue #2277). Fixed an issue with reloading a SED-ML file / COMBINE archive potentially crashing OpenCOR (see issue #2290)." },
+ { "change": "Third-party libraries: upgraded LLVM+Clang to version 9.0.1 (see issue #2269). Upgraded the SUNDIALS library to version 5.1.0 (see issue #2272). Upgraded libgit2 to version 0.28.4 (see issue #2280). Upgraded Mesa to version 19.3.2 (see issue #2281)." }
+ ]
+ },
{ "major": 0, "minor": 0, "patch": 0, "day": 13, "month": 12, "year": 2019, "type": 2, "license": 2,
"platforms": [
{ "name": "Windows", "supported": "Windows 7 and later",
diff --git a/doc/whatIsNew.js b/doc/whatIsNew.js
index 281a6a1e86..8f15ca16db 100644
--- a/doc/whatIsNew.js
+++ b/doc/whatIsNew.js
@@ -26,6 +26,7 @@ var jsonData = { "versions": [
"entries": [
{ "type": "subCategory", "name": "CellML Text view",
"entries": [
+ { "type": "improved", "description": "Rendering of the GUI." },
{ "type": "fixed", "description": "Reading a CellML file that has no XML processing instruction." }
]
}
diff --git a/src/plugins/editing/CellMLTextView/src/cellmltextviewlexer.cpp b/src/plugins/editing/CellMLTextView/src/cellmltextviewlexer.cpp
index 9a9a10fbaf..408df7d392 100644
--- a/src/plugins/editing/CellMLTextView/src/cellmltextviewlexer.cpp
+++ b/src/plugins/editing/CellMLTextView/src/cellmltextviewlexer.cpp
@@ -130,50 +130,72 @@ QFont CellmlTextViewLexer::font(int pStyle) const
//==============================================================================
-void CellmlTextViewLexer::styleText(int pBytesStart, int pBytesEnd)
+static const int StyleChunk = 32768;
+
+//==============================================================================
+
+void CellmlTextViewLexer::styleText(int pStart, int pEnd)
{
+#ifdef QT_DEBUG
// Make sure that we have an editor
if (editor() == nullptr) {
- return;
+ qFatal("FATAL ERROR | %s:%d: styling can only be performed with an editor.", __FILE__, __LINE__);
}
+#endif
- // Retrieve the text to style
+ // Keep track of some information
- auto data = new char[pBytesEnd-pBytesStart+1] {};
+ mFullText = editor()->text().toUtf8();
+ mEolString = qobject_cast(editor())->eolString();
- editor()->SendScintilla(QsciScintilla::SCI_GETTEXTRANGE,
- pBytesStart, pBytesEnd, data);
+ // Style the text in small chunks (to reduce memory usage, which can quickly
+ // become ridiculous the first time we are styling a big CellML file)
- QString text = QString(data);
+ int start = pStart;
+ int end;
- delete[] data;
+ forever {
+ // Use a default style for our chunk of text
+ // Note: this is so that validString() can work properly...
- // Use a default style for our text
- // Note: this is so that validString() can work properly...
+ end = qMin(start+StyleChunk, pEnd);
- startStyling(pBytesStart);
- setStyling(pBytesEnd-pBytesStart, int(Style::Default));
+ applyStyle(start, end, Style::Default);
- // Effectively style our text
+ // Retrieve the chunk of text to style and style it
- mFullText = editor()->text();
- mFullTextUtf8 = mFullText.toUtf8();
+ auto data = new char[end-start+1] {};
- mEolString = qobject_cast(editor())->eolString();
+ editor()->SendScintilla(QsciScintilla::SCI_GETTEXTRANGE,
+ start, end, data);
- styleText(pBytesStart, pBytesEnd, text, false);
+ styleText(start, end, data, false);
+
+ delete[] data;
#ifdef QT_DEBUG
- // Make sure that the end position of the last bit of text that we styled is
- // pBytesEnd
- // Note: we need to ensure that it is the case, so that validString() can
- // take advantage of the style of a given character in the editor...
+ // Make sure that the end position of the last bit of chunk of text that
+ // we styled is end
+ // Note: we need to ensure that it is the case, so that validString()
+ // can take advantage of the style of a given character in the
+ // editor...
+
+ if (editor()->SendScintilla(QsciScintillaBase::SCI_GETENDSTYLED) != end) {
+ qFatal("FATAL ERROR | %s:%d: the styling of the text must be incremental.", __FILE__, __LINE__);
+ }
+#endif
+
+ // Was it our last chunk of text?
+
+ if (end == pEnd) {
+ break;
+ }
+
+ // Get ready for the next chunk of text
- if (editor()->SendScintilla(QsciScintillaBase::SCI_GETENDSTYLED) != pBytesEnd) {
- qFatal("FATAL ERROR | %s:%d: the styling of the text must be incremental.", __FILE__, __LINE__);
+ start = end;
}
-#endif
// Let people know that we are done with our styling
@@ -205,66 +227,92 @@ static const int StringLength = 1;
//==============================================================================
-void CellmlTextViewLexer::styleText(int pBytesStart, int pBytesEnd,
- const QString &pText, bool pParameterBlock)
+void CellmlTextViewLexer::applyStyle(int pStart, int pEnd, Style pStyle)
+{
+ // Apply the given style to the given chunk of text
+
+ startStyling(pStart);
+ setStyling(pEnd-pStart, int(pStyle));
+}
+
+//==============================================================================
+
+void CellmlTextViewLexer::styleText(int pStart, int pEnd,
+ const QByteArray &pText,
+ bool pParameterBlock)
{
// Make sure that we are given some text to style
- if (pBytesStart == pBytesEnd) {
+ if (pStart == pEnd) {
return;
}
// Check whether a /* XXX */ comment or a parameter block started before or
// at the beginning of the given text
- int start = fullTextPosition(pBytesStart);
- int multilineCommentStartPosition = findString(StartMultilineCommentString, start, int(Style::MultilineComment), false);
- int parameterBlockStartPosition = findString(StartParameterBlockString, start, int(Style::ParameterBlock), false);
+ int multilineCommentStartPosition = findString(StartMultilineCommentString, pStart, Style::MultilineComment, false);
+ int parameterBlockStartPosition = findString(StartParameterBlockString, pStart, Style::ParameterBlock, false);
- multilineCommentStartPosition = (multilineCommentStartPosition == -1)?INT_MAX:multilineCommentStartPosition;
- parameterBlockStartPosition = (parameterBlockStartPosition == -1)?INT_MAX:parameterBlockStartPosition;
+ multilineCommentStartPosition = (multilineCommentStartPosition == -1)?
+ INT_MAX:
+ multilineCommentStartPosition;
+ parameterBlockStartPosition = (parameterBlockStartPosition == -1)?
+ INT_MAX:
+ parameterBlockStartPosition;
- int multilineCommentEndPosition = (multilineCommentStartPosition == INT_MAX)?INT_MAX:findString(EndMultilineCommentString, multilineCommentStartPosition, int(Style::MultilineComment));
- int parameterBlockEndPosition = (parameterBlockStartPosition == INT_MAX)?INT_MAX:findString(EndParameterBlockString, parameterBlockStartPosition, int(Style::ParameterBlock));
+ int multilineCommentEndPosition = (multilineCommentStartPosition == INT_MAX)?
+ INT_MAX:
+ findString(EndMultilineCommentString, multilineCommentStartPosition, Style::MultilineComment);
- multilineCommentEndPosition = (multilineCommentEndPosition == -1)?INT_MAX:multilineCommentEndPosition;
- parameterBlockEndPosition = (parameterBlockEndPosition == -1)?INT_MAX:parameterBlockEndPosition;
+ multilineCommentEndPosition = (multilineCommentEndPosition == -1)?
+ INT_MAX:
+ multilineCommentEndPosition;
if ( (multilineCommentStartPosition != INT_MAX)
&& ( (parameterBlockStartPosition == INT_MAX)
|| ( (multilineCommentStartPosition > parameterBlockStartPosition)
- && (multilineCommentEndPosition > start)))) {
+ && (multilineCommentEndPosition > pStart)))) {
// There is a previous /* XXX */ comment to style
styleTextPreviousMultilineComment(multilineCommentStartPosition,
- pBytesStart, pBytesEnd,
+ pStart, pEnd,
pText, pParameterBlock);
- } else if ( (parameterBlockStartPosition != INT_MAX)
- && ( (multilineCommentStartPosition == INT_MAX)
- || ( (parameterBlockStartPosition > multilineCommentStartPosition)
- && (parameterBlockEndPosition > start)))) {
- // There is a previous parameter block to style
-
- styleTextPreviousParameterBlock(parameterBlockStartPosition,
- pBytesStart, pBytesEnd,
- pText, pParameterBlock);
} else {
- // Style the current text
+ int parameterBlockEndPosition = (parameterBlockStartPosition == INT_MAX)?
+ INT_MAX:
+ findString(EndParameterBlockString, parameterBlockStartPosition, Style::ParameterBlock);
+
+ parameterBlockEndPosition = (parameterBlockEndPosition == -1)?
+ INT_MAX:
+ parameterBlockEndPosition;
+
+ if ( (parameterBlockStartPosition != INT_MAX)
+ && ( (multilineCommentStartPosition == INT_MAX)
+ || ( (parameterBlockStartPosition > multilineCommentStartPosition)
+ && (parameterBlockEndPosition > pStart)))) {
+ // There is a previous parameter block to style
+
+ styleTextPreviousParameterBlock(parameterBlockStartPosition,
+ pStart, pEnd,
+ pText, pParameterBlock);
+ } else {
+ // Style the current text
- styleTextCurrent(pBytesStart, pBytesEnd, pText,
- (parameterBlockStartPosition < start) && (parameterBlockEndPosition > start));
+ styleTextCurrent(pStart, pEnd, pText,
+ (parameterBlockStartPosition < pStart) && (parameterBlockEndPosition > pStart));
+ }
}
}
//==============================================================================
-void CellmlTextViewLexer::styleTextCurrent(int pBytesStart, int pBytesEnd,
- const QString &pText,
+void CellmlTextViewLexer::styleTextCurrent(int pStart, int pEnd,
+ const QByteArray &pText,
bool pParameterBlock)
{
// Make sure that we are given some text to style
- if (pBytesStart == pBytesEnd) {
+ if (pStart == pEnd) {
return;
}
@@ -274,28 +322,30 @@ void CellmlTextViewLexer::styleTextCurrent(int pBytesStart, int pBytesEnd,
int stringPosition = pText.indexOf(StringString);
int singleLineCommentPosition = pText.indexOf(SingleLineCommentString);
int multilineCommentStartPosition = pText.indexOf(StartMultilineCommentString);
- int parameterBlockStartPosition = pText.indexOf(StartParameterBlockString);
- stringPosition = (stringPosition == -1)?INT_MAX:stringPosition;
- singleLineCommentPosition = (singleLineCommentPosition == -1)?INT_MAX:singleLineCommentPosition;
- multilineCommentStartPosition = (multilineCommentStartPosition == -1)?INT_MAX:multilineCommentStartPosition;
- parameterBlockStartPosition = (parameterBlockStartPosition == -1)?INT_MAX:parameterBlockStartPosition;
+ stringPosition = (stringPosition == -1)?
+ INT_MAX:
+ stringPosition;
+ singleLineCommentPosition = (singleLineCommentPosition == -1)?
+ INT_MAX:
+ singleLineCommentPosition;
+ multilineCommentStartPosition = (multilineCommentStartPosition == -1)?
+ INT_MAX:
+ multilineCommentStartPosition;
if ( (stringPosition != INT_MAX)
&& (stringPosition < singleLineCommentPosition)
&& (stringPosition < multilineCommentStartPosition)) {
// There is a string to style
- styleTextString(stringPosition, pBytesStart, pBytesEnd, pText, pParameterBlock);
+ styleTextString(stringPosition, pStart, pEnd, pText, pParameterBlock);
} else if ( (singleLineCommentPosition != INT_MAX)
&& (singleLineCommentPosition < stringPosition)
&& (singleLineCommentPosition < multilineCommentStartPosition)) {
// There is a // comment to style, so first style everything that is
// before it
- int singleLineCommentBytesPosition = fullTextBytesPosition(fullTextPosition(pBytesStart)+singleLineCommentPosition);
-
- styleTextCurrent(pBytesStart, singleLineCommentBytesPosition,
+ styleTextCurrent(pStart, pStart+singleLineCommentPosition,
pText.left(singleLineCommentPosition),
pParameterBlock);
@@ -303,18 +353,14 @@ void CellmlTextViewLexer::styleTextCurrent(int pBytesStart, int pBytesEnd,
// line, if any
int eolPosition = pText.indexOf(mEolString, singleLineCommentPosition+SingleLineCommentLength);
- int eolBytesPosition = (eolPosition == -1)?-1:textBytesPosition(pText, eolPosition);
- int end = (eolBytesPosition == -1)?pBytesEnd:pBytesStart+eolBytesPosition+mEolString.length();
+ int end = (eolPosition == -1)?pEnd:pStart+eolPosition+mEolString.length();
- startStyling(singleLineCommentBytesPosition);
- setStyling(end-singleLineCommentBytesPosition, int(Style::SingleLineComment));
+ applyStyle(pStart+singleLineCommentPosition, end, Style::SingleLineComment);
// Now, style everything that is after the // comment, if anything
- if (eolBytesPosition != -1) {
- styleText(end, pBytesEnd,
- pText.right(fullTextLength(end, pBytesEnd)),
- pParameterBlock);
+ if (eolPosition != -1) {
+ styleText(end, pEnd, pText.right(pEnd-end), pParameterBlock);
}
} else if ( (multilineCommentStartPosition != INT_MAX)
&& (multilineCommentStartPosition < stringPosition)
@@ -322,9 +368,7 @@ void CellmlTextViewLexer::styleTextCurrent(int pBytesStart, int pBytesEnd,
// There is a /* XXX */ comment to style, so first style everything that
// is before it
- int multilineCommentStartBytesPosition = fullTextBytesPosition(fullTextPosition(pBytesStart)+multilineCommentStartPosition);
-
- styleTextCurrent(pBytesStart, multilineCommentStartBytesPosition,
+ styleTextCurrent(pStart, pStart+multilineCommentStartPosition,
pText.left(multilineCommentStartPosition),
pParameterBlock);
@@ -337,178 +381,188 @@ void CellmlTextViewLexer::styleTextCurrent(int pBytesStart, int pBytesEnd,
// we need to finish styling it (which is effectively done in
// styleTextPreviousMultilineComment())...
- int start = fullTextPosition(pBytesStart);
- int multilineCommentParameterBlockStartPosition = findString(StartParameterBlockString, start+multilineCommentStartPosition, int(Style::ParameterBlock), false);
- int multilineCommentParameterBlockEndPosition = findString(EndParameterBlockString, multilineCommentParameterBlockStartPosition, int(Style::ParameterBlock));
+ int multilineCommentParameterBlockStartPosition = findString(StartParameterBlockString, pStart+multilineCommentStartPosition, Style::ParameterBlock, false);
+ int multilineCommentParameterBlockEndPosition = findString(EndParameterBlockString, multilineCommentParameterBlockStartPosition, Style::ParameterBlock);
- multilineCommentParameterBlockStartPosition = (multilineCommentParameterBlockStartPosition == -1)?INT_MAX:multilineCommentParameterBlockStartPosition;
- multilineCommentParameterBlockEndPosition = (multilineCommentParameterBlockEndPosition == -1)?INT_MAX:multilineCommentParameterBlockEndPosition;
+ multilineCommentParameterBlockStartPosition = (multilineCommentParameterBlockStartPosition == -1)?
+ INT_MAX:
+ multilineCommentParameterBlockStartPosition;
+ multilineCommentParameterBlockEndPosition = (multilineCommentParameterBlockEndPosition == -1)?
+ INT_MAX:
+ multilineCommentParameterBlockEndPosition;
- int absoluteMultilineCommentStartPosition = start+multilineCommentStartPosition;
+ int absoluteMultilineCommentStartPosition = pStart+multilineCommentStartPosition;
- styleText(multilineCommentStartBytesPosition, pBytesEnd,
- pText.right(fullTextLength(multilineCommentStartBytesPosition, pBytesEnd)),
+ styleText(pStart+multilineCommentStartPosition, pEnd,
+ pText.right(pEnd-pStart-multilineCommentStartPosition),
(multilineCommentParameterBlockStartPosition < absoluteMultilineCommentStartPosition)
&& (absoluteMultilineCommentStartPosition < multilineCommentParameterBlockEndPosition));
- } else if ( (parameterBlockStartPosition != INT_MAX)
- && (parameterBlockStartPosition < stringPosition)
- && (parameterBlockStartPosition < singleLineCommentPosition)
- && (parameterBlockStartPosition < multilineCommentStartPosition)) {
- // There is a parameter block, so first style everything that is before
- // it
+ } else {
+ int parameterBlockStartPosition = pText.indexOf(StartParameterBlockString);
+
+ parameterBlockStartPosition = (parameterBlockStartPosition == -1)?
+ INT_MAX:
+ parameterBlockStartPosition;
+
+ if ( (parameterBlockStartPosition != INT_MAX)
+ && (parameterBlockStartPosition < stringPosition)
+ && (parameterBlockStartPosition < singleLineCommentPosition)
+ && (parameterBlockStartPosition < multilineCommentStartPosition)) {
+ // There is a parameter block, so first style everything that is
+ // before it
+
+ styleTextCurrent(pStart, pStart+parameterBlockStartPosition,
+ pText.left(parameterBlockStartPosition),
+ pParameterBlock);
+
+ // Now style everything from the parameter block onwards
+ // Note: to style everything from the parameter block onwards means
+ // that we will find that a parameter block starts at the
+ // beginning of the 'new' given text...
+
+ styleText(pStart+parameterBlockStartPosition, pEnd,
+ pText.right(pEnd-pStart-parameterBlockStartPosition),
+ pParameterBlock);
+ } else {
+ // Style the given text as a parameter block, if needed
- int parameterBlockStartBytesPosition = fullTextBytesPosition(fullTextPosition(pBytesStart)+parameterBlockStartPosition);
+ if (pParameterBlock) {
+ applyStyle(pStart, pEnd, Style::ParameterBlock);
+ }
- styleTextCurrent(pBytesStart, parameterBlockStartBytesPosition,
- pText.left(parameterBlockStartPosition),
- pParameterBlock);
+ // Check whether the given text contains some keywords from various
+ // categories
- // Now style everything from the parameter block onwards
- // Note: to style everything from the parameter block onwards means that
- // we will find that a parameter block starts at the beginning of
- // the 'new' given text...
+ static const QRegularExpression KeywordsRegEx = QRegularExpression(
+ "\\b("
+ // CellML Text keywords
- styleText(parameterBlockStartBytesPosition, pBytesEnd,
- pText.right(fullTextLength(parameterBlockStartBytesPosition, pBytesEnd)),
- pParameterBlock);
- } else {
- // Style the given text as a parameter block, if needed
+ "and|as|between|case|comp|def|endcomp|enddef|endsel|for|"
+ "group|import|incl|map|model|otherwise|sel|unit|using|var|"
+ "vars|"
- if (pParameterBlock) {
- startStyling(pBytesStart);
- setStyling(pBytesEnd-pBytesStart, int(Style::ParameterBlock));
- }
+ // MathML arithmetic operators
- // Check whether the given text contains some keywords from various
- // categories
+ "abs|ceil|exp|fact|floor|ln|log|pow|root|sqr|sqrt|"
- static const QRegularExpression KeywordsRegEx = QRegularExpression(
- "\\b("
- // CellML Text keywords
+ // MathML logical operators
- "and|as|between|case|comp|def|endcomp|enddef|endsel|for|group|"
- "import|incl|map|model|otherwise|sel|unit|using|var|vars|"
+ "and|or|xor|not|"
- // MathML arithmetic operators
+ // MathML calculus elements
- "abs|ceil|exp|fact|floor|ln|log|pow|root|sqr|sqrt|"
+ "ode|"
- // MathML logical operators
+ // MathML min/max operators
- "and|or|xor|not|"
+ "min|max|"
- // MathML calculus elements
+ // MathML gcd/lcm operators
- "ode|"
+ "gcd|lcm|"
- // MathML min/max operators
+ // MathML trigonometric operators
- "min|max|"
+ "sin|cos|tan|sec|csc|cot|sinh|cosh|tanh|sech|csch|coth|"
+ "asin|acos|atan|asec|acsc|acot|asinh|acosh|atanh|asech|"
+ "acsch|acoth|"
- // MathML gcd/lcm operators
+ // MathML constants
- "gcd|lcm|"
+ "true|false|nan|pi|inf|e|"
- // MathML trigonometric operators
+ // Extra operators
- "sin|cos|tan|sec|csc|cot|sinh|cosh|tanh|sech|csch|coth|asin|"
- "acos|atan|asec|acsc|acot|asinh|acosh|atanh|asech|acsch|acoth|"
+ "rem"
+ ")\\b");
- // MathML constants
+ static const QRegularExpression CellmlKeywordsRegEx = QRegularExpression(
+ "\\b("
+ // Miscellaneous
- "true|false|nan|pi|inf|e|"
+ "base|encapsulation|containment"
+ ")\\b");
- // Extra operators
+ static const QRegularExpression ParameterKeywordsRegEx = QRegularExpression(
+ "\\b("
+ // Unit keywords
- "rem"
- ")\\b");
+ "pref|expo|mult|off|"
- static const QRegularExpression CellmlKeywordsRegEx = QRegularExpression(
- "\\b("
- // Miscellaneous
+ // Variable keywords
- "base|encapsulation|containment"
- ")\\b");
+ "init|pub|priv"
+ ")\\b");
- static const QRegularExpression ParameterKeywordsRegEx = QRegularExpression(
- "\\b("
- // Unit keywords
+ static const QRegularExpression ParameterCellmlKeywordsRegEx = QRegularExpression(
+ "\\b("
+ // Unit prefixes
- "pref|expo|mult|off|"
+ "yotta|zetta|exa|peta|tera|giga|mega|kilo|hecto|deka|deci|"
+ "centi|milli|micro|nano|pico|femto|atto|zepto|yocto|"
- // Variable keywords
+ // Public/private interfaces
- "init|pub|priv"
- ")\\b");
+ "in|out|none"
+ ")\\b");
- static const QRegularExpression ParameterCellmlKeywordsRegEx = QRegularExpression(
- "\\b("
- // Unit prefixes
+ static const QRegularExpression SiUnitKeywordsRegEx = QRegularExpression(
+ "\\b("
+ // Standard units
- "yotta|zetta|exa|peta|tera|giga|mega|kilo|hecto|deka|deci|"
- "centi|milli|micro|nano|pico|femto|atto|zepto|yocto|"
+ "ampere|becquerel|candela|celsius|coulomb|dimensionless|"
+ "farad|gram|gray|henry|hertz|joule|katal|kelvin|kilogram|"
+ "liter|litre|lumen|lux|meter|metre|mole|newton|ohm|pascal|"
+ "radian|second|siemens|sievert|steradian|tesla|volt|watt|"
+ "weber"
+ ")\\b");
+
+ if (pParameterBlock) {
+ styleTextRegEx(pStart, pText, ParameterKeywordsRegEx, Style::ParameterKeyword);
+ styleTextRegEx(pStart, pText, ParameterCellmlKeywordsRegEx, Style::ParameterCellmlKeyword);
+ } else {
+ styleTextRegEx(pStart, pText, KeywordsRegEx, Style::Keyword);
+ styleTextRegEx(pStart, pText, CellmlKeywordsRegEx, Style::CellmlKeyword);
+ }
- // Public/private interfaces
+ styleTextRegEx(pStart, pText, SiUnitKeywordsRegEx,
+ pParameterBlock?
+ Style::ParameterCellmlKeyword:
+ Style::CellmlKeyword);
- "in|out|none"
- ")\\b");
+ // Check whether the given text contains some numbers
- static const QRegularExpression SiUnitKeywordsRegEx = QRegularExpression(
- "\\b("
- // Standard units
+ styleTextNumber(pStart, pText, pParameterBlock?
+ Style::ParameterNumber:
+ Style::Number);
- "ampere|becquerel|candela|celsius|coulomb|dimensionless|farad|"
- "gram|gray|henry|hertz|joule|katal|kelvin|kilogram|liter|litre|"
- "lumen|lux|meter|metre|mole|newton|ohm|pascal|radian|second|"
- "siemens|sievert|steradian|tesla|volt|watt|weber"
- ")\\b");
+ // Let QScintilla know that we are done with the styling of the
+ // given text
+ // Note: indeed, QScintilla uses the end position of the last bit of
+ // text that has been styled to determine the starting
+ // position of the next bit of text that needs to be styled
+ // (see QsciLexerCustom::handleStyleNeeded()). Now, depending
+ // on whether keywords and/or numbers have been styled, the
+ // end position may or not be pEnd. So, here, we make sure
+ // that it is, so that QScintilla can work as it should...
- if (pParameterBlock) {
- styleTextRegEx(pBytesStart, pText, ParameterKeywordsRegEx, int(Style::ParameterKeyword));
- styleTextRegEx(pBytesStart, pText, ParameterCellmlKeywordsRegEx, int(Style::ParameterCellmlKeyword));
- } else {
- styleTextRegEx(pBytesStart, pText, KeywordsRegEx, int(Style::Keyword));
- styleTextRegEx(pBytesStart, pText, CellmlKeywordsRegEx, int(Style::CellmlKeyword));
+ startStyling(pEnd);
}
-
- styleTextRegEx(pBytesStart, pText, SiUnitKeywordsRegEx,
- pParameterBlock?
- int(Style::ParameterCellmlKeyword):
- int(Style::CellmlKeyword));
-
- // Check whether the given text contains some numbers
-
- styleTextNumberRegEx(pBytesStart, pText,
- pParameterBlock?
- int(Style::ParameterNumber):
- int(Style::Number));
-
- // Let QScintilla know that we are done with the styling of the given
- // text
- // Note: indeed, QScintilla uses the end position of the last bit of
- // text that has been styled to determine the starting position of
- // the next bit of text that needs to be styled (see
- // QsciLexerCustom::handleStyleNeeded()). Now, depending on
- // whether keywords and/or numbers have been styled, the end
- // position may or not be pBytesEnd. So, here, we make sure that
- // it is, so that QScintilla can work as it should...
-
- startStyling(pBytesEnd);
}
}
//==============================================================================
void CellmlTextViewLexer::styleTextPreviousMultilineComment(int pPosition,
- int pBytesStart,
- int pBytesEnd,
- const QString &pText,
+ int pStart,
+ int pEnd,
+ const QByteArray &pText,
bool pParameterBlock)
{
// A /* XXX */ comment started before or at the beginning of the given text,
// so now look for where it ends
- int multilineCommentEndPosition = findString(EndMultilineCommentString, pPosition, int(Style::MultilineComment));
+ int multilineCommentEndPosition = findString(EndMultilineCommentString, pPosition, Style::MultilineComment);
if (multilineCommentEndPosition == -1) {
multilineCommentEndPosition = mFullText.length();
@@ -517,55 +571,47 @@ void CellmlTextViewLexer::styleTextPreviousMultilineComment(int pPosition,
// Check whether the beginning of the given text is within the /* XXX */
// comment
- int start = fullTextPosition(pBytesStart);
-
- if ((pPosition <= start) && (start <= multilineCommentEndPosition)) {
+ if ((pPosition <= pStart) && (pStart <= multilineCommentEndPosition)) {
// The beginning of the given text is within a /* XXX */ comment, so
// style it
- int realBytesEnd = fullTextBytesPosition(multilineCommentEndPosition)+EndMultilineCommentLength;
- int bytesEnd = qMin(pBytesEnd, realBytesEnd);
+ int realEnd = multilineCommentEndPosition+EndMultilineCommentLength;
+ int end = qMin(pEnd, realEnd);
- startStyling(pBytesStart);
- setStyling(bytesEnd-pBytesStart, int(Style::MultilineComment));
+ applyStyle(pStart, end, Style::MultilineComment);
// Now, style everything that is behind the /* XXX */ comment, if
// anything
- if (bytesEnd != pBytesEnd) {
+ if (end != pEnd) {
if (pParameterBlock) {
// Our /* XXX */ comment is within a parameter block, so finish
// styling our parameter block
- styleTextPreviousParameterBlock(fullTextPosition(bytesEnd), bytesEnd, pBytesEnd,
- pText.right(fullTextLength(bytesEnd, pBytesEnd)),
- false);
+ styleTextPreviousParameterBlock(end, end, pEnd, pText.right(pEnd-end), false);
} else {
- styleText(bytesEnd, pBytesEnd,
- pText.right(fullTextLength(bytesEnd, pBytesEnd)),
- pParameterBlock);
+ styleText(end, pEnd, pText.right(pEnd-end), pParameterBlock);
}
}
} else {
// The beginning of the given text is not within a /* XXX */ comment, so
// style it
- styleTextCurrent(pBytesStart, pBytesEnd, pText, pParameterBlock);
+ styleTextCurrent(pStart, pEnd, pText, pParameterBlock);
}
}
//==============================================================================
void CellmlTextViewLexer::styleTextPreviousParameterBlock(int pPosition,
- int pBytesStart,
- int pBytesEnd,
- const QString &pText,
+ int pStart, int pEnd,
+ const QByteArray &pText,
bool pParameterBlock)
{
// A parameter block started before or at the beginning of the given text,
// so now look for where it ends
- int parameterBlockEndPosition = findString(EndParameterBlockString, pPosition, int(Style::ParameterBlock));
+ int parameterBlockEndPosition = findString(EndParameterBlockString, pPosition, Style::ParameterBlock);
if (parameterBlockEndPosition == -1) {
parameterBlockEndPosition = mFullText.length();
@@ -573,69 +619,60 @@ void CellmlTextViewLexer::styleTextPreviousParameterBlock(int pPosition,
// Check whether the beginning of the given text is within a parameter block
- int start = fullTextPosition(pBytesStart);
-
- if ((pPosition <= start) && (start <= parameterBlockEndPosition)) {
+ if ((pPosition <= pStart) && (pStart <= parameterBlockEndPosition)) {
// The beginning of the given text is within a parameter block, so style
// it as such
- int realBytesEnd = fullTextBytesPosition(parameterBlockEndPosition)+EndParameterBlockLength;
- int bytesEnd = qMin(pBytesEnd, realBytesEnd);
- bool hasStart = (pPosition == start)
+ int realEnd = parameterBlockEndPosition+EndParameterBlockLength;
+ int end = qMin(pEnd, realEnd);
+ bool hasStart = (pPosition == pStart)
&& (mFullText.mid(pPosition, StartParameterBlockLength) == StartParameterBlockString);
- bool hasEnd = bytesEnd == realBytesEnd;
+ bool hasEnd = end == realEnd;
// If needed, style the start of the parameter block
if (hasStart) {
- startStyling(pBytesStart);
- setStyling(StartParameterBlockLength, int(Style::ParameterBlock));
+ applyStyle(pStart, pStart+StartParameterBlockLength, Style::ParameterBlock);
}
// Now style the contents of the parameter block itself
- int newBytesStart = pBytesStart+(hasStart?StartParameterBlockLength:0);
- int newBytesEnd = bytesEnd-(hasEnd?EndParameterBlockLength:0);
+ int newStart = pStart+(hasStart?StartParameterBlockLength:0);
+ int newEnd = end-(hasEnd?EndParameterBlockLength:0);
- styleTextCurrent(newBytesStart, newBytesEnd,
- pText.mid(fullTextLength(pBytesStart, newBytesStart),
- fullTextLength(newBytesStart, newBytesEnd)),
- true);
+ styleTextCurrent(newStart, newEnd, pText.mid(newStart-pStart, newEnd-newStart), true);
// If needed, style the end of the parameter block, as well as what is
// behind it
if (hasEnd) {
- startStyling(bytesEnd-EndParameterBlockLength);
- setStyling(EndParameterBlockLength, int(Style::ParameterBlock));
+ applyStyle(end-EndParameterBlockLength, end, Style::ParameterBlock);
- styleText(bytesEnd, pBytesEnd,
- pText.right(fullTextLength(bytesEnd, pBytesEnd)),
- pParameterBlock);
+ styleText(end, pEnd, pText.right(pEnd-end), pParameterBlock);
}
} else {
// The beginning of the given text is not within a parameter block, so
// style it
- styleTextCurrent(pBytesStart, pBytesEnd, pText, pParameterBlock);
+ styleTextCurrent(pStart, pEnd, pText, pParameterBlock);
}
}
//==============================================================================
-void CellmlTextViewLexer::styleTextString(int pPosition, int pBytesStart,
- int pBytesEnd, const QString &pText,
+void CellmlTextViewLexer::styleTextString(int pPosition, int pStart, int pEnd,
+ const QByteArray &pText,
bool pParameterBlock)
{
// There is a string to style, so first style everything that is before it
- int bytesPosition = fullTextBytesPosition(fullTextPosition(pBytesStart)+pPosition);
+ int position = pStart+pPosition;
- styleTextCurrent(pBytesStart, bytesPosition, pText.left(pPosition), pParameterBlock);
+ styleTextCurrent(pStart, position, pText.left(pPosition), pParameterBlock);
// Now, check where the string ends, if anywhere
- int nextBytesStart = -1;
+ int nextStart = -1;
int stringEndPosition = pText.indexOf(StringString, pPosition+StringLength);
if (stringEndPosition != -1) {
@@ -644,18 +681,17 @@ void CellmlTextViewLexer::styleTextString(int pPosition, int pBytesStart,
int stringStartLineNumber, stringStartColumnNumber;
int stringEndLineNumber, stringEndColumnNumber;
- int stringEndBytesPosition = textBytesPosition(pText, stringEndPosition);
- editor()->lineIndexFromPosition(bytesPosition,
+ editor()->lineIndexFromPosition(position,
&stringStartLineNumber, &stringStartColumnNumber);
- editor()->lineIndexFromPosition(pBytesStart+stringEndBytesPosition,
+ editor()->lineIndexFromPosition(pStart+stringEndPosition,
&stringEndLineNumber, &stringEndColumnNumber);
if (stringStartLineNumber == stringEndLineNumber) {
// The string starts and ends on the same line, so get ready to
// style everything that is after the string
- nextBytesStart = pBytesStart+stringEndBytesPosition+StringLength;
+ nextStart = pStart+stringEndPosition+StringLength;
} else {
// The string starts and ends on a different line, so consider that
// we couldn't find the end of the string
@@ -670,60 +706,53 @@ void CellmlTextViewLexer::styleTextString(int pPosition, int pBytesStart,
// end of the line, if anything, on which the string started
int eolPosition = pText.indexOf(mEolString, pPosition+StringLength);
- int eolBytesPosition = (eolPosition == -1)?-1:textBytesPosition(pText, eolPosition);
- if (eolBytesPosition != -1) {
- nextBytesStart = pBytesStart+eolBytesPosition+mEolString.length();
+ if (eolPosition != -1) {
+ nextStart = pStart+eolPosition+mEolString.length();
}
}
// Style the string itself
- startStyling(bytesPosition);
- setStyling(((nextBytesStart == -1)?pBytesEnd:nextBytesStart)-bytesPosition,
+ applyStyle(position,
+ (nextStart == -1)?
+ pEnd:
+ nextStart,
pParameterBlock?
- int(Style::ParameterString):
- int(Style::String));
+ Style::ParameterString:
+ Style::String);
// Style whatever is after the string
- if (nextBytesStart != -1) {
- styleText(nextBytesStart, pBytesEnd,
- pText.right(fullTextLength(nextBytesStart, pBytesEnd)),
- pParameterBlock);
+ if (nextStart != -1) {
+ styleText(nextStart, pEnd, pText.right(pEnd-nextStart), pParameterBlock);
}
}
//==============================================================================
-void CellmlTextViewLexer::styleTextRegEx(int pBytesStart,
- const QString &pText,
+void CellmlTextViewLexer::styleTextRegEx(int pStart, const QByteArray &pText,
const QRegularExpression &pRegEx,
- int pRegExStyle)
+ Style pStyle)
{
// Style the given text using the given regular expression
QRegularExpressionMatchIterator regExMatchIter = pRegEx.globalMatch(pText);
- QRegularExpressionMatch regExMatch;
while (regExMatchIter.hasNext()) {
- regExMatch = regExMatchIter.next();
-
// We have a match, so style it
- int matchBytesStart = textBytesPosition(pText, regExMatch.capturedStart());
+ QRegularExpressionMatch regExMatch = regExMatchIter.next();
+ int capturedStart = regExMatch.capturedStart();
- startStyling(pBytesStart+matchBytesStart);
- setStyling(textBytesPosition(pText, regExMatch.capturedStart()+regExMatch.capturedLength())-matchBytesStart,
- pRegExStyle);
+ applyStyle(pStart+capturedStart, pStart+capturedStart+regExMatch.capturedLength(), pStyle);
}
}
//==============================================================================
-void CellmlTextViewLexer::styleTextNumberRegEx(int pBytesStart,
- const QString &pText,
- int pRegExStyle)
+void CellmlTextViewLexer::styleTextNumber(int pStart, const QByteArray &pText,
+ Style pStyle)
{
// Style the given text using the number regular expression
@@ -733,52 +762,53 @@ void CellmlTextViewLexer::styleTextNumberRegEx(int pBytesStart,
// want to be able to catch "123e")...
QRegularExpressionMatchIterator regExMatchIter = NumberRegEx.globalMatch(pText);
- QRegularExpressionMatch regExMatch;
while (regExMatchIter.hasNext()) {
- regExMatch = regExMatchIter.next();
-
// We have a match, so style it, but only if:
// - The character in front of the match is not in [0-9a-zA-Z_] and is
// part of the ASCII table
// - The character following the match is not in [a-zA-Z_.] and is part
// of the ASCII table
- int prevCharPos = fullTextPosition(pBytesStart)+regExMatch.capturedStart()-1;
- int nextCharPos = prevCharPos+regExMatch.capturedLength()+1;
-
- ushort prevChar = ((prevCharPos >= 0)?mFullText[prevCharPos]:QChar()).unicode();
- ushort nextChar = ((nextCharPos < mFullText.length())?mFullText[nextCharPos]:QChar()).unicode();
-
- if (( (prevChar < 48) || ((prevChar > 57) && (prevChar < 65))
+ QRegularExpressionMatch regExMatch = regExMatchIter.next();
+ int capturedStart = regExMatch.capturedStart();
+ int capturedLength = regExMatch.capturedLength();
+ int prevCharPos = pStart+capturedStart-1;
+ int nextCharPos = prevCharPos+capturedLength+1;
+
+ char prevChar = (prevCharPos >= 0)?
+ mFullText[prevCharPos]:
+ 0;
+ char nextChar = (nextCharPos < mFullText.length())?
+ mFullText[nextCharPos]:
+ 0;
+
+ if ( ( (prevChar < 48)
+ || ((prevChar > 57) && (prevChar < 65))
|| ((prevChar > 90) && (prevChar < 95))
- || (prevChar == 96) || ((prevChar > 122) && (prevChar < 128)))
- && ( (nextChar < 46) || ((nextChar > 46) && (nextChar < 65))
+ || (prevChar == 96)
+ || (prevChar > 122))
+ && ( (nextChar < 46)
+ || ((nextChar > 46) && (nextChar < 65))
|| ((nextChar > 90) && (nextChar < 95))
- || (nextChar == 96) || ((nextChar > 122) && (nextChar < 128)))) {
- int matchBytesStart = textBytesPosition(pText, regExMatch.capturedStart());
-
- startStyling(pBytesStart+matchBytesStart);
- setStyling(textBytesPosition(pText, regExMatch.capturedStart()+regExMatch.capturedLength())-matchBytesStart,
- pRegExStyle);
+ || (nextChar == 96)
+ || (nextChar > 122))) {
+ applyStyle(pStart+capturedStart, pStart+capturedStart+capturedLength, pStyle);
}
}
}
//==============================================================================
-bool CellmlTextViewLexer::validString(int pFrom, int pTo, int pStyle) const
+bool CellmlTextViewLexer::validString(int pFrom, int pTo, Style pStyle) const
{
// Check whether the string, which range is given, is valid, i.e. is either
// of the default or given style
- qint64 style;
-
for (int i = pFrom; i < pTo; ++i) {
- style = editor()->SendScintilla(QsciScintilla::SCI_GETSTYLEAT,
- fullTextBytesPosition(i));
+ Style style = Style(editor()->SendScintilla(QsciScintilla::SCI_GETSTYLEAT, i));
- if ((style != int(Style::Default)) && (style != pStyle)) {
+ if ((style != Style::Default) && (style != pStyle)) {
return false;
}
}
@@ -788,8 +818,8 @@ bool CellmlTextViewLexer::validString(int pFrom, int pTo, int pStyle) const
//==============================================================================
-int CellmlTextViewLexer::findString(const QString &pString, int pFrom,
- int pStyle, bool pForward)
+int CellmlTextViewLexer::findString(const QByteArray &pString, int pFrom,
+ Style pStyle, bool pForward)
{
// Find forward/backward the given string starting from the given position
@@ -807,45 +837,6 @@ int CellmlTextViewLexer::findString(const QString &pString, int pFrom,
//==============================================================================
-int CellmlTextViewLexer::fullTextPosition(int pBytesPosition) const
-{
- // Return the corresponding position within mFullText of the given
- // byte-based position within mFullTextUtf8
-
- return QString(mFullTextUtf8.left(pBytesPosition)).length();
-}
-
-//==============================================================================
-
-int CellmlTextViewLexer::fullTextLength(int pBytesStart, int pBytesEnd) const
-{
- // Return the corresponding length within mFullText of the given byte-based
- // length of a substring within mFullTextUtf8
-
- return fullTextPosition(pBytesEnd)-fullTextPosition(pBytesStart);
-}
-
-//==============================================================================
-
-int CellmlTextViewLexer::fullTextBytesPosition(int pPosition) const
-{
- // Return the byte-based value of the given position within mFullText
-
- return mFullText.left(pPosition).toUtf8().length();
-}
-
-//==============================================================================
-
-int CellmlTextViewLexer::textBytesPosition(const QString &pText,
- int pPosition) const
-{
- // Return the byte-based value of the given position within the given text
-
- return pText.left(pPosition).toUtf8().length();
-}
-
-//==============================================================================
-
} // namespace CellMLTextView
} // namespace OpenCOR
diff --git a/src/plugins/editing/CellMLTextView/src/cellmltextviewlexer.h b/src/plugins/editing/CellMLTextView/src/cellmltextviewlexer.h
index 1b4d683721..c46d28049f 100644
--- a/src/plugins/editing/CellMLTextView/src/cellmltextviewlexer.h
+++ b/src/plugins/editing/CellMLTextView/src/cellmltextviewlexer.h
@@ -69,41 +69,34 @@ class CellmlTextViewLexer : public QsciLexerCustom
QColor color(int pStyle) const override;
QFont font(int pStyle) const override;
- void styleText(int pBytesStart, int pBytesEnd) override;
+ void styleText(int pStart, int pEnd) override;
private:
- QString mFullText;
- QByteArray mFullTextUtf8;
+ QByteArray mFullText;
+ QByteArray mEolString;
- QString mEolString;
-
- void styleText(int pBytesStart, int pBytesEnd, const QString &pText,
+ void applyStyle(int pStart, int pEnd, Style pStyle);
+ void styleText(int pStart, int pEnd, const QByteArray &pText,
bool pParameterBlock);
- void styleTextCurrent(int pBytesStart, int pBytesEnd, const QString &pText,
+ void styleTextCurrent(int pStart, int pEnd, const QByteArray &pText,
bool pParameterBlock);
- void styleTextPreviousMultilineComment(int pPosition, int pBytesStart,
- int pBytesEnd, const QString &pText,
+ void styleTextPreviousMultilineComment(int pPosition, int pStart, int pEnd,
+ const QByteArray &pText,
bool pParameterBlock);
- void styleTextPreviousParameterBlock(int pPosition, int pBytesStart,
- int pBytesEnd, const QString &pText,
+ void styleTextPreviousParameterBlock(int pPosition, int pStart, int pEnd,
+ const QByteArray &pText,
bool pParameterBlock);
- void styleTextString(int pPosition, int pBytesStart, int pBytesEnd,
- const QString &pText, bool pParameterBlock);
- void styleTextRegEx(int pBytesStart, const QString &pText,
- const QRegularExpression &pRegEx, int pRegExStyle);
- void styleTextNumberRegEx(int pBytesStart, const QString &pText,
- int pRegExStyle);
-
- bool validString(int pFrom, int pTo, int pStyle) const;
- int findString(const QString &pString, int pFrom, int pStyle,
+ void styleTextString(int pPosition, int pStart, int pEnd,
+ const QByteArray &pText, bool pParameterBlock);
+ void styleTextRegEx(int pStart, const QByteArray &pText,
+ const QRegularExpression &pRegEx, Style pStyle);
+ void styleTextNumber(int pStart, const QByteArray &pText,
+ Style pStyle);
+
+ bool validString(int pFrom, int pTo, Style pStyle) const;
+ int findString(const QByteArray &pString, int pFrom, Style pStyle,
bool pForward = true);
- int fullTextPosition(int pBytesPosition) const;
- int fullTextLength(int pBytesStart, int pBytesEnd) const;
-
- int fullTextBytesPosition(int pPosition) const;
- int textBytesPosition(const QString &pText, int pPosition) const;
-
signals:
void done();
};
diff --git a/src/plugins/widget/QScintillaWidget/src/qscintillawidget.cpp b/src/plugins/widget/QScintillaWidget/src/qscintillawidget.cpp
index 9ffbf75853..6e7941666b 100644
--- a/src/plugins/widget/QScintillaWidget/src/qscintillawidget.cpp
+++ b/src/plugins/widget/QScintillaWidget/src/qscintillawidget.cpp
@@ -405,7 +405,7 @@ QLabel * QScintillaWidget::editingModeWidget() const
//==============================================================================
-QString QScintillaWidget::eolString() const
+QByteArray QScintillaWidget::eolString() const
{
// Return the end of line we use
diff --git a/src/plugins/widget/QScintillaWidget/src/qscintillawidget.h b/src/plugins/widget/QScintillaWidget/src/qscintillawidget.h
index 4f71fd637c..92784b396b 100644
--- a/src/plugins/widget/QScintillaWidget/src/qscintillawidget.h
+++ b/src/plugins/widget/QScintillaWidget/src/qscintillawidget.h
@@ -96,7 +96,7 @@ class QSCINTILLAWIDGET_EXPORT QScintillaWidget : public QsciScintilla
QLabel * cursorPositionWidget() const;
QLabel * editingModeWidget() const;
- QString eolString() const;
+ QByteArray eolString() const;
QColor backgroundColor(int pStyle);
void setBackgroundColor(int pStyle, const QColor &pBackgroundColor);