Results 1 to 5 of 5

Thread: Unexpected QTextCursor behaviour

  1. #1
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Unexpected QTextCursor behaviour

    Hey,

    I'm trying to catch the users input in a QTextEdit and check for illegal characters.

    I catch the signal "textChanged()" and check the input (edit->toPlainText()) for illegal characters.

    If some illegal characters are found, I replace or remove them and set the new text (edit->setPlainText(QString)).

    Now my problem is the cursor position. I found out that calling QTextEdit::setPlainText(QString) sets a new QTextCursor at position '0'.

    I manage this by saving the QTextCursor's recent position (before changing input) and set this position to the new QTextCursor, like this:
    Qt Code:
    1. this->blockSignals(true);
    2. QString input = this->toPlainText();
    3.  
    4. // ... some checks and replaces with input
    5.  
    6. QTextCursor cursor = this->textCursor();
    7. int cursorPos = this->textCursor().position();
    8.  
    9. this->setPlainText(input); // this deletes the previous cursor
    10.  
    11. cursor.setPosition(cursorPos);
    12. this->setTextCursor(cursor);
    13.  
    14. this->blockSignals(false);
    To copy to clipboard, switch view to plain text mode 

    This works great. What I don't under stand is, why the following code (exactly the same commands, only different order) doesn't work:
    Qt Code:
    1. this->blockSignals(true);
    2. QString input = this->toPlainText();
    3.  
    4. // ... some checks and replaces with input
    5.  
    6. QTextCursor cursor = this->textCursor();
    7. int cursorPos = this->textCursor().position();
    8. cursor.setPosition(cursorPos);
    9.  
    10. this->setPlainText(input); // this deletes the previous cursor
    11.  
    12. this->setTextCursor(cursor);
    13.  
    14. this->blockSignals(false);
    To copy to clipboard, switch view to plain text mode 
    I would understand that if "cursor" was a pointer, but it isn't!! How can QTextEdit recognize that I set the new cursor position before setting new text?

    I would really appreciate a good explanation of this strange behaviour...

    Thank you in anticipation!
    Binary

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Unexpected QTextCursor behaviour

    The object might not be a pointer, but the objects internally could easily have a permanent relationship.

    E.g. a QAbstractItemModel knows about the QPersistentModelIndex instances it created and can update them in necessary.

    Cheers,
    _

  3. #3
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Re: Unexpected QTextCursor behaviour

    Hi,

    hm that confuses me a bit. How does Qt manage this?

    Let's take the example above. I have a QTextEdit that internaly has a QTextCursor member (non-pointer).

    In my function, I create a new QTextCursor object that should be a copy of the QTextEdit's QTextCursor:
    Qt Code:
    1. QTextCursor cursorCopy = edit->textCursor();
    To copy to clipboard, switch view to plain text mode 
    Question 1: How does Qt manage this now? How can Qt have a connection between this copy and the internal QTextCursor of QTextEdit if it is just a copy, not a pointer??

    Question 2: If you were right and there exists any mystic connection between the copy and the original QTextCursor, then the following should work, too:
    Qt Code:
    1. edit->textCursor().setPosition(int);
    To copy to clipboard, switch view to plain text mode 
    But it doesn't work. I can only set a new cursor position by changing the cursor position in the copy and replacing the original QTextCursor with the copy by:
    Qt Code:
    1. edit->setTextCursor(QTextCursor);
    To copy to clipboard, switch view to plain text mode 
    Well, for me it seems to be logical that it doesn't work, because:
    Qt Code:
    1. edit->textCursor();
    To copy to clipboard, switch view to plain text mode 
    only gives me a copy, so changing cursor postion via:
    Qt Code:
    1. edit->textCursor().setPosition(int);
    To copy to clipboard, switch view to plain text mode 
    will never apply to QTextEdit but only to the copy.

    So after all, I'm still wondering about this behaviour. Why does it have some features like a pointer with a real connection to QTextEdit's textcursor when the code above fails (like it is expected for a non-pointer copy) ??

    Sorry but I really want to understand that...

  4. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Unexpected QTextCursor behaviour

    Quote Originally Posted by Binary91 View Post
    hm that confuses me a bit. How does Qt manage this?

    Let's take the example above. I have a QTextEdit that internaly has a QTextCursor member (non-pointer).

    In my function, I create a new QTextCursor object that should be a copy of the QTextEdit's QTextCursor:
    Qt Code:
    1. QTextCursor cursorCopy = edit->textCursor();
    To copy to clipboard, switch view to plain text mode 
    Question 1: How does Qt manage this now? How can Qt have a connection between this copy and the internal QTextCursor of QTextEdit if it is just a copy, not a pointer??
    The QTextCursor holds a pointer to the QTexDocument that created it. And it registers itself with the document.
    So both objects know each other.
    If you create a copy, the new copy also registers itself with the document.


    Quote Originally Posted by Binary91 View Post
    Question 2: If you were right and there exists any mystic connection between the copy and the original QTextCursor, then the following should work, too:
    Qt Code:
    1. edit->textCursor().setPosition(int);
    To copy to clipboard, switch view to plain text mode 
    But it doesn't work.
    That changes the position of the tempory copy. Since that object is not the document's "current cursor" it doesn't affect the document.

    Quote Originally Posted by Binary91 View Post
    I can only set a new cursor position by changing the cursor position in the copy and replacing the original QTextCursor with the copy by:
    Qt Code:
    1. edit->setTextCursor(QTextCursor);
    To copy to clipboard, switch view to plain text mode 
    That replaces the document's "current cursor" with the one you pass in.

    Quote Originally Posted by Binary91 View Post
    Well, for me it seems to be logical that it doesn't work, because:
    Qt Code:
    1. edit->textCursor();
    To copy to clipboard, switch view to plain text mode 
    only gives me a copy, so changing cursor postion via:
    Qt Code:
    1. edit->textCursor().setPosition(int);
    To copy to clipboard, switch view to plain text mode 
    will never apply to QTextEdit but only to the copy.
    Yes.

    Quote Originally Posted by Binary91 View Post
    Sorry but I really want to understand that...
    In your first variant, you save the position. Then you implicitly clear the document by setting totally new content.
    All cursors get their position reset.
    Then you modify one cursor with the saved position.
    You then set a cursor that now has position == saved position.

    In your second variant, you set the cursor's position. Then you implicitly clear the document by setting totally new content.
    All cursors get their positions reset.
    You then set a cursor that now has position == 0.

    See QTextDocumentPrivate::clear(), qtextdocument_p.cpp


    Cheers,
    _

  5. #5
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Re: Unexpected QTextCursor behaviour

    Hi,

    at first, thank you for you explanations!

    Well, if I understand you right, QTextDocument is the "mother" or "parent" of QTextCursor and the original QTextCursor has a pointer to it and by copying it to my new QTextCursor I also copy the pointer to QTextDocument, so the "mystic" connection goes through QTextDocument.

    That would make sense, if the copy exactly changed its position like the original QTextCursor (what I thought till a view minutes ago).

    Let's take the example again:
    Qt Code:
    1. this->blockSignals(true);
    2.  
    3. QTextCursor cursorCopy = edit->textCursor();
    4. int intCursorPosPre = edit->textCursor().position();
    5. QMessageBox::information(this, "Before changing QTextDocument", QString::number(edit->textCursor().position()) + "\n" + QString::number(cursorCopy.position()));
    6. this->setPlainText(stringText);
    7. QMessageBox::information(this, "After changing QTextDocument", QString::number(edit->textCursor().position()) + "\n" + QString::number(cursorCopy.position()));
    8. if(intTextLengthPre == intTextLengthPost)
    9. cursorCopy.setPosition(intCursorPosPre);
    10. else
    11. cursorCopy.setPosition(intCursorPosPre-1);
    12. QMessageBox::information(this, "After setting previously saved position to cursorCopy", QString::number(edit->textCursor().position()) + "\n" + QString::number(cursorCopy.position()));
    13. edit->setTextCursor(cursorCopy);
    14. QMessageBox::information(this, "After setting cursorCopy to cursorOriginal", QString::number(edit->textCursor().position()) + "\n" + QString::number(cursorCopy.position()));
    15.  
    16. this->blockSignals(false);
    To copy to clipboard, switch view to plain text mode 
    Well, I found out, that when "stringText" did not change in prior algorithms (hence, QTextEdit is updated with the same text it had before), then the following:
    Qt Code:
    1. edit->setPlainText(QString);
    To copy to clipboard, switch view to plain text mode 
    only changes the cursorOriginal (it sets it to zero). The cursorCopy is not changed, hence its position is always the same and I don't need to save it into an int...

    Instead, when "stringText" changes in prior algorithms (e.g. it was shorten from length 10 to length 9 characters), then:
    Qt Code:
    1. edit->setPlainText(QString);
    To copy to clipboard, switch view to plain text mode 
    sets the cursorOriginal to zero again, BUT the cursorCopy increments by 1!

    Can you explain this behaviour to me? It seems that it is not that easy that both, the cursorOriginal and the cursorCopy, change identically...

    EDIT:
    Ah after trying some constellations, I detected the rule in this behaviour:
    After setting new text:
    Qt Code:
    1. edit->setPlainText(QString);
    To copy to clipboard, switch view to plain text mode 
    the cursorOriginal always sets to zero and the cursorCopy always sets to the last possible position!!

    But I still don't see a reason or a sense behind this behaviour!
    Last edited by Binary91; 10th July 2015 at 13:58.

Similar Threads

  1. Replies: 1
    Last Post: 28th February 2014, 17:01
  2. Link Error and Unexpected Finish
    By decoy in forum Newbie
    Replies: 1
    Last Post: 14th June 2012, 02:43
  3. Unexpected behavior with commits and rollbacks...
    By mtnbiker66 in forum Qt Programming
    Replies: 6
    Last Post: 6th June 2012, 16:06
  4. Unexpected build errors in a Qt project
    By prykHetQuo in forum Qt Programming
    Replies: 2
    Last Post: 24th January 2010, 22:33
  5. QTabWidget->setCornerWidget() unexpected resize.
    By hickscorp in forum Qt Programming
    Replies: 7
    Last Post: 20th December 2006, 15:12

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.