So far, when deleting the selected text, the proper lines are reported as being deleted when the selection is deleted be a key command (delete or backspace) or replaced by typing a character. The cut and delete actions (from the Edit menu or tool bar) also need to be handled.
The cut() function from the QPlainTextEdit class was reimplemented in the EditBox class and a call to the QplainTextEdit::cut() function was added. Before this call, the current selection is saved. After the call, the function implemented for key press deletion of selections that detects deleted lines is called.
The remove() function was already implemented to delete the selected text (not to the clipboard). Similar to the new cut() function, the selection is saved before the text is deleted and the deleted lines are captured afterward.
[commit 5c3e16f9e8]
Saturday, February 2, 2013
Deleted Lines From Selections (Keys)
There are quite a few situations to handle with detecting changed, deleted or inserted lines when selection text is involved. When there is selected text, it needs to determined if the selection is on one line or several lines. If text is being pastes on top of a selection (replacing it), it needs to determined if the pasted text is one line or several lines. Each of these situations will be handled one at a time to make this more manageable.
The first situation to be handled is when text has been selected and either a character is typed (the selected text is replaced with the character), or a delete command key is entered (delete or backspace). After the key has been entered, if there was a selection before the key is processed, it needs to determine how many lines may have been deleted and report these lines. The line the cursor is left on is set as the modified line, which will be reported when the cursor leaves the line.
To capture the selection before the key is processed (it won't be there after the key is processed), the particulars of the selection need to be saved, namely, whether there was a selection, and the starting and ending line of the selection. Because of implicit sharing, which the QTextCursor class supports, a copy of it before processing the key can not be made because the copy will be updated when the key is processed (the selection goes away).
To simplify the process of saving the selection particulars, a new Selection class was implemented with members for the start and end positions and the start and end line numbers of the selection. Because the document is changed when the key is processed, the start and end positions can't be used afterward except to check if there was a selection (the positions are not the same). This class has functions to set these variables from the text cursor (called before a key is processed), check if the selection is empty, get the number of lines in the selection (ending line minus starting line plus one), and accessors for the starting and ending line numbers.
The code needs to know if something was actually deleted by the key command before checking if lines were deleted (the command may have just moved the selection). There is a signal from the document like the general document changed signal, but includes the position of the change along with the number of characters removed and added. This signal was connected to a new slot function to capture and store the number of characters removed and added.
A new function was implemented to capture any lines that may have been deleted when there was a selection. This function checks if there was a selection before the operation, and there were characters removed. If the selection was more than one line, then the lines starting with the selection's starting line for the number of lines minus one are reported as being deleted. The number of characters removed and added are reset to zero so further operations don't erroneously report more lines being deleted.
If the selection, was on one line, no lines need to be reported. The current line modified is already being set when the document changed signal was received, so only lines below the cursor line need to be reported as being deleted. When the cursor leaves this line, the line will be reported as being changed.
[commit 1c0c27c744]
The first situation to be handled is when text has been selected and either a character is typed (the selected text is replaced with the character), or a delete command key is entered (delete or backspace). After the key has been entered, if there was a selection before the key is processed, it needs to determine how many lines may have been deleted and report these lines. The line the cursor is left on is set as the modified line, which will be reported when the cursor leaves the line.
To capture the selection before the key is processed (it won't be there after the key is processed), the particulars of the selection need to be saved, namely, whether there was a selection, and the starting and ending line of the selection. Because of implicit sharing, which the QTextCursor class supports, a copy of it before processing the key can not be made because the copy will be updated when the key is processed (the selection goes away).
To simplify the process of saving the selection particulars, a new Selection class was implemented with members for the start and end positions and the start and end line numbers of the selection. Because the document is changed when the key is processed, the start and end positions can't be used afterward except to check if there was a selection (the positions are not the same). This class has functions to set these variables from the text cursor (called before a key is processed), check if the selection is empty, get the number of lines in the selection (ending line minus starting line plus one), and accessors for the starting and ending line numbers.
The code needs to know if something was actually deleted by the key command before checking if lines were deleted (the command may have just moved the selection). There is a signal from the document like the general document changed signal, but includes the position of the change along with the number of characters removed and added. This signal was connected to a new slot function to capture and store the number of characters removed and added.
A new function was implemented to capture any lines that may have been deleted when there was a selection. This function checks if there was a selection before the operation, and there were characters removed. If the selection was more than one line, then the lines starting with the selection's starting line for the number of lines minus one are reported as being deleted. The number of characters removed and added are reset to zero so further operations don't erroneously report more lines being deleted.
If the selection, was on one line, no lines need to be reported. The current line modified is already being set when the document changed signal was received, so only lines below the cursor line need to be reported as being deleted. When the cursor leaves this line, the line will be reported as being changed.
[commit 1c0c27c744]
Edit Box – Line Numbers
One of the things making the development of detecting line changes involving selections difficult is not seeing which lines are being referred to by the line numbers being reported without continuously counting lines on the screen. Therefore, lines numbers were added to the edit box. How to do this was discovered in the Code Editor Example in the Qt documentation, which was linked to from the QPlainTextEdit help page. It can also be found by search for "Code Editor" using the help page search.
This code was utilized in the edit box with several changes (only the code dealing with line numbers was used). The example contains documentation, but this code essentially adds a widget on the left side of the edit box text area. The background color of this widget is set to light gray and the line numbers are drawn into this widget.
The example code only made the width of the line number widget wide enough to hold the maximum line number plus three pixels on the left side of the numbers. This made the line numbers look bunched in, so a full space was added to each side of the numbers.
The example code also started line numbers at one, but the line numbers in the document actually start at zero. This needs to be taken account when calculating the widget of the line number widget and when drawing the line numbers to the widget. However, for debugging purposes (the reason line numbers were added), it makes more sense to start the line numbers at zero. Therefore, a BaseLineNumber definition was added to set the base line number. For debugging, this will be set to a zero, but once this is no longer needed, this definition will be set to one.
[commit 0c67d5b69c]
This code was utilized in the edit box with several changes (only the code dealing with line numbers was used). The example contains documentation, but this code essentially adds a widget on the left side of the edit box text area. The background color of this widget is set to light gray and the line numbers are drawn into this widget.
The example code only made the width of the line number widget wide enough to hold the maximum line number plus three pixels on the left side of the numbers. This made the line numbers look bunched in, so a full space was added to each side of the numbers.
The example code also started line numbers at one, but the line numbers in the document actually start at zero. This needs to be taken account when calculating the widget of the line number widget and when drawing the line numbers to the widget. However, for debugging purposes (the reason line numbers were added), it makes more sense to start the line numbers at zero. Therefore, a BaseLineNumber definition was added to set the base line number. For debugging, this will be set to a zero, but once this is no longer needed, this definition will be set to one.
[commit 0c67d5b69c]
Edit Box - Plain Text Edit
Detecting line changes when selections are involved is turning out to be a rather involved. In doing research on a number of things, I discovered that there is a QPlainTextEdit class, which is a much simpler version of the QTextEdit class, and is more appropriate for a code editor. Namely, QTextEdit is more complex and can handle rich text (text with formatting, which was disabled for EditBox), lists and tables.
The QPlainTextEdit class only handles plain text, and will also handle larger files more efficiently. Fortunately, this class will still support syntax highlighting and other highlighting that will be needed for EditBox including highlighting errors.
To switch EditBox to using this class as its base class, all that was needed was changing all instances of QTextEdit to QPlainTextEdit. The call to setAcceptRichText() with a false argument was no longer needed. And there is no such concept of a current font (QPlainTextEdit only has one font), so in order to set the font to the desired fixed width font, the font() and setFont() access functions inherited from QWidget are used to set the font of the edit box.
[commit 497c46a9fa]
The QPlainTextEdit class only handles plain text, and will also handle larger files more efficiently. Fortunately, this class will still support syntax highlighting and other highlighting that will be needed for EditBox including highlighting errors.
To switch EditBox to using this class as its base class, all that was needed was changing all instances of QTextEdit to QPlainTextEdit. The call to setAcceptRichText() with a false argument was no longer needed. And there is no such concept of a current font (QPlainTextEdit only has one font), so in order to set the font to the desired fixed width font, the font() and setFont() access functions inherited from QWidget are used to set the font of the edit box.
[commit 497c46a9fa]
Subscribe to:
Posts (Atom)