From 64610d43be70e308db0bfd6d52a88f00ef8e767e Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Thu, 30 Jan 2020 18:11:26 +1300 Subject: [PATCH] CellML Text view: style a CellML file in chunks (#2284). This means that for very big CellML file we don't end up with OpenCOR using GBs of RAM. --- .../src/cellmltextviewlexer.cpp | 73 +++++++++++++------ 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/src/plugins/editing/CellMLTextView/src/cellmltextviewlexer.cpp b/src/plugins/editing/CellMLTextView/src/cellmltextviewlexer.cpp index e1760caf1b..5489163cad 100644 --- a/src/plugins/editing/CellMLTextView/src/cellmltextviewlexer.cpp +++ b/src/plugins/editing/CellMLTextView/src/cellmltextviewlexer.cpp @@ -130,6 +130,10 @@ QFont CellmlTextViewLexer::font(int pStyle) const //============================================================================== +static const int StyleChunk = 2048; + +//============================================================================== + void CellmlTextViewLexer::styleText(int pBytesStart, int pBytesEnd) { #ifdef QT_DEBUG @@ -140,42 +144,67 @@ void CellmlTextViewLexer::styleText(int pBytesStart, int pBytesEnd) } #endif - // Retrieve the text to style + // Keep track of some information - auto data = new char[pBytesEnd-pBytesStart+1] {}; + mFullText = editor()->text(); + mFullTextUtf8 = mFullText.toUtf8(); - editor()->SendScintilla(QsciScintilla::SCI_GETTEXTRANGE, - pBytesStart, pBytesEnd, data); + mEolString = qobject_cast(editor())->eolString(); - QString text = QString(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) - delete[] data; + int bytesStart = pBytesStart; + int bytesEnd; - // Use a default style for our text - // Note: this is so that validString() can work properly... + forever { + // Style a chunk of text - startStyling(pBytesStart); - setStyling(pBytesEnd-pBytesStart, int(Style::Default)); + bytesEnd = qMin(bytesStart+StyleChunk, pBytesEnd); - // Effectively style our text + // Retrieve the chunk of text to style - mFullText = editor()->text(); - mFullTextUtf8 = mFullText.toUtf8(); + auto data = new char[bytesEnd-bytesStart+1] {}; - mEolString = qobject_cast(editor())->eolString(); + editor()->SendScintilla(QsciScintilla::SCI_GETTEXTRANGE, + bytesStart, bytesEnd, data); + + QString text = QString(data); + + delete[] data; - styleText(pBytesStart, pBytesEnd, text, false); + // Use a default style for our chunk text + // Note: this is so that validString() can work properly... + + startStyling(bytesStart); + setStyling(bytesEnd-bytesStart, int(Style::Default)); + + // Effectively style our chunk of text + + styleText(bytesStart, bytesEnd, text, false); #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 bytesEnd + // 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) != bytesEnd) { + qFatal("FATAL ERROR | %s:%d: the styling of the text must be incremental.", __FILE__, __LINE__); + } +#endif - if (editor()->SendScintilla(QsciScintillaBase::SCI_GETENDSTYLED) != pBytesEnd) { - qFatal("FATAL ERROR | %s:%d: the styling of the text must be incremental.", __FILE__, __LINE__); + // Was it our last chunk of text? + + if (bytesEnd == pBytesEnd) { + break; + } + + // Get ready for the next chunk of text + + bytesStart = bytesEnd; } -#endif // Let people know that we are done with our styling