QSyntaxHighlighter Does Not Highlight Correctly



  • Hello friends.

    I'm back here, I'm doing some tests with an example code of Qt, but the truth is giving me headaches.

    Specifically I'm doing the following example http://doc.qt.io/qt-5/qtwidgets-richtext-syntaxhighlighter-example.html, which obviously works, including the modifications I've made work as well. Jejeje, So where is the problem? Lol, a joke, now well and seriously.

    I have applied the same strategy for the comment highlighting that is explained in the example to apply it to other type of comments that are of type documentation to the style JavaDoc, that is to say:

    / **
     *
     * /

    While the example explains how to do this for the multiline C++ comment type:

    / *
     * Any comments
     * Another comment line
     * /

    The application of the code is exactly the same or so I think: /. The detail is, if I only apply the JavaDoc-style implementation, it works fine. If I only apply the multiline C++ comment style implementation, it also works fine, but if I put both implementations, the JavaDoc style highlighting applies well. The multiline C++ comment style, I only highlight the first line, and the rest leave it as if it were normal text.

    From what I have researched in the documentation on the Qt Scribe framework, the order in which the rules are processed is important, which I have also noticed in the process of implementing the comment highlighting in the JavaDoc style, That I must first process the multiline C++ comment and then the JavaDoc style.

    On the other hand, a curious fact, is that if I place the multilinea comments in a single line, I highlight everything well, that is:

    / * * Any comment * another comment line * /

    I hope you can give me some hand with this problem. I searched the forum but I can not get something to guide me to solve this problem.

    Note that this highlighting that I am applying should be shown in another color to the multilinea comments of C++

    Thanks in advance.


  • Lifetime Qt Champion

    Hi,

    Do you mean you have that with the example implementation ? If not, can you share your modifications ?



  • Hi SGaist, thanks for your answer and my apologies for not putting the code to illustrate my problem.

    Yes, I have the implementation of the example plus the portion of code I added, which is exactly the same as the example used for the multiline highlighting, except that I modified the regular expression for the start of the doccomment. Here I show my code so they can see the problem.

    In the highlighter.h file

    QRegExp docCommentStartExpression;
    QRegExp docCommentEndExpression;
    QTextCharFormat multiLinedocCommentFormat;
    

    In the highlighter.cpp file, specifically in the constructor

    docCommentStartExpression = QRegExp ( "/\\*\\*" );
    docCommentEndExpression = QRegExp ( "\\*/" );
    multiLinedocCommentFormat.setForeground ( Qt::darkBlue );
    

    In the highlighter.cpp file, specifically in the highlightBlock method

      foreach ( const HighlightingRule &rule, this->highlightingRules ) {
    
        QRegExp expression ( rule.getPattern () );
        int index = expression.indexIn(text);
        while ( index >= 0 ) {
    
          int length = expression.matchedLength ();
          this->setFormat ( index, length, rule.getFormat () );
          index = expression.indexIn ( text, index + length );
        }
      }
    
      /**
       * Code for multiline comments
       */
      this->setCurrentBlockState ( 0 );
    
      int startIndex = 0;
      if ( this->previousBlockState () != 1 ) {
    
        startIndex = commentStartExpression.indexIn ( text );
      }
    
      while ( startIndex >= 0 ) {
    
        int endIndex = commentEndExpression.indexIn ( text, startIndex );
        int commentLength;
        if ( endIndex == -1 ) {
    
            this->setCurrentBlockState ( 1 );
            commentLength = text.length () - startIndex;
    
        } else {
    
            commentLength = endIndex - startIndex + commentEndExpression.matchedLength ();
        }
        this->setFormat ( startIndex, commentLength, multiLineCommentFormat );
        startIndex = commentStartExpression.indexIn ( text, startIndex + commentLength );
      }
    
      /**
       * Code for javadoc style doccomment
       */
      this->setCurrentBlockState ( 0 );
    
      startIndex = 0;
      if ( this->previousBlockState () != 1 ) {
    
        startIndex = docCommentStartExpression.indexIn ( text );
      }
    
      while ( startIndex >= 0 ) {
    
        int endIndex = docCommentEndExpression.indexIn ( text, startIndex );
        int commentLength;
        if ( endIndex == -1 ) {
    
            this->setCurrentBlockState ( 1 );
            commentLength = text.length () - startIndex;
    
        } else {
    
            commentLength = endIndex - startIndex + commentEndExpression.matchedLength ();
        }
        this->setFormat ( startIndex, commentLength, multiLinedocCommentFormat );
        startIndex = docCommentStartExpression.indexIn ( text, startIndex + commentLength );
      }
    

    As you can see, within the implementation of the highlightBlock (const QString & text) method that shows the example, I used the code section for multiline comments, to implement an additional functionality that is to show documentation comments to the javadoc style , And that's the code section for the javadoc style doccomment.

    As I said initially, if I only apply the code for multiline comments, these comments are fine, if I only apply the code for javdoc style comments, these are also shown well. If I apply both implementations, they are shown as follows:

    for multiline comments highlighting
    /* // This is shown in red
     * <strong>EcoMca</strong>  // This is shown in black
     */ // This is shown in black
    
    for doc comments highlighting
    This is all shown in blue
    /*
     * <strong>EcoMca</strong>
     */
    

    For the multiline comment highlighter, I left the same colors as the example, because I just wanted to focus on the new functionality that I want to implement, and for this functionality that I'm trying to apply I've placed a blue highlighting.

    This is the only thing I have modified, the rest of the example is intact.

    I hope now if the problem has been well explained ;)


  • Lifetime Qt Champion

    The thing here is that you have two expressions that are covering the same use case with one covering a broader set of character. So basically, you need to first check for the narrower expression and if it doesn't match continue with the broader.

    Not that QRegExp is deprecated with Qt 5, you should use QRegularExpression.



  • Hello again, friends.

    I've finally managed to get the two types of comment blocks, the multiline block, and javadoc-style comments shown. Although the idea was more or less directed, it was necessary to make a more specific management of the type of block on which it was being handled.

    Well you had to make a distinction between the multiline comment block and the javadoc style comment block and at the end of each block do a "block close" with the setCurrentBlockState (-1) method.

    And here the code in question. As I said the beginning of this thread is based on the example provided by Qt in the documentation.

    foreach ( const HighlightingRule &rule, this->highlightingRules ) {
    
        QRegExp expression ( rule.getPattern () );
        int index = expression.indexIn(text);
        while ( index >= 0 ) {
    
          int length = expression.matchedLength ();
          this->setFormat ( index, length, rule.getFormat () );
          index = expression.indexIn ( text, index + length );
        }
      }
    
      int startIndex = 0;
      if ( ( this->previousBlockState () != 1 ) && ( this->previousBlockState () != 2 ) ) {
    
        startIndex = docCommentStartExpression.indexIn ( text );
        if ( startIndex == -1 ) {
    
          startIndex = commentStartExpression.indexIn ( text );
          if ( startIndex >= 0 ) {
    
            this->setCurrentBlockState ( 1 );
          }
        } else {
    
          this->setCurrentBlockState ( 2 );
        }
      }
    
      while ( startIndex >= 0 ) {
    
        int endIndex = 0;
        int commentLength;
        if ( ( this->currentBlockState () == 1 ) || ( this->previousBlockState () == 1 ) ) {
    
          endIndex = commentEndExpression.indexIn ( text, startIndex );
          if ( endIndex == -1 ) {
    
            this->setCurrentBlockState ( 1 );
            commentLength = text.length () - startIndex;
    
          } else {
    
            this->setCurrentBlockState ( -1 );
            commentLength = endIndex - startIndex + commentEndExpression.matchedLength ();
          }
          this->setFormat ( startIndex, commentLength, multiLineCommentFormat );
          startIndex = commentStartExpression.indexIn ( text, startIndex + commentLength );
    
        } else if ( ( this->currentBlockState () == 2 ) || ( this->previousBlockState () == 2 ) ) {
    
          endIndex = docCommentEndExpression.indexIn ( text, startIndex );
          if ( endIndex == -1 ) {
    
            this->setCurrentBlockState ( 2 );
            commentLength = text.length () - startIndex;
    
          } else {
    
            this->setCurrentBlockState ( -1 );
            commentLength = endIndex - startIndex + docCommentEndExpression.matchedLength ();
          }
          this->setFormat ( startIndex, commentLength, multiLinedocCommentFormat );
          startIndex = docCommentStartExpression.indexIn ( text, startIndex + commentLength );
        }
      }
    

    Yes SGaist, you're right about QRegExp, just that I'm doing tests on the sample code from QSyntaxHighlighter, but now that I've completed the idea I start with the optimization. JEJEJE

    Thank you very much for your help and guidance.

    And I hope someone will help you.


  • Lifetime Qt Champion

    The example has been updated ;) But I think it will appear with Qt 5.9.


Log in to reply