In order to detect lines that may be modified of inserted text from pasting, the text that is about to be inserted from the clipboard needs to be intercepted and examined to see what is about to be inserted. To catch the paste action, the paste function was reimplemented in the EditBox class. The paste key sequence also needed to be intercepted, so the key press event handler was modified to also call this new paste function for the paste key sequence.
In the new paste function, a pointer to the clipboard is obtained from the static QApplication::clipboard() function. The plain text contents of the clipboard is obtained by calling text() function. Since the existing function for inserting a new line contained a subset of the code needed for inserting text which may contain new lines. So this function was modified to handle more than just inserting a single new line. This new function is called for the return key with a string containing a single new line character.
The insert text function handles determining whether the current line (before inserting the text) needs to be reported as changed, if any new lines need to be reported as inserted, and what to set the modified status of the cursor line once the text has been inserted. Right now this function only handles a paste when there is no text selected.
[commit 8b46b474f1]
Sunday, February 10, 2013
Saturday, February 9, 2013
Another Backspace Issue
While testing the line detection code when pasting, another backspace issue was discovered. If the current line was modified, and the backspace is used at the beginning of the line to combine is with the previous line that is blank, it was not preserving the modified status of the line (the modified line was being reset always).
To correct this, if the previous line is blank and the current line is modified, then the modified line variable is decremented to reflect the line number of the current line after the backspace (combine) operation is performed. Only if the previous line is not blank is the modified line reset.
Since the backspace functionality is getting rather large, it was moved into its own function. It was also noticed that the check for if the current line is blank (which sets the ignore change flag since the previous line won't actually be modified), was in both parts of the if statement, these lines were moved outside the if statement.
[commit cd7200da0e] [commit ee9e2ee6a4]
To correct this, if the previous line is blank and the current line is modified, then the modified line variable is decremented to reflect the line number of the current line after the backspace (combine) operation is performed. Only if the previous line is not blank is the modified line reset.
Since the backspace functionality is getting rather large, it was moved into its own function. It was also noticed that the check for if the current line is blank (which sets the ignore change flag since the previous line won't actually be modified), was in both parts of the if statement, these lines were moved outside the if statement.
[commit cd7200da0e] [commit ee9e2ee6a4]
Thursday, February 7, 2013
Minor Backspace Issue
The backspace was not completely debugged. When backspacing at the beginning of the line, and the line was not reported yet because it was a new line (insert modification type), the modification type was suppose to be reset back to line changed type (see the Two Issues post from a few days ago). However, the equality operator was used instead of the assignment operator, so it was actually resetting it.
[commit 13443cd8ce]
[commit 13443cd8ce]
Wednesday, February 6, 2013
Line Changes and Blank Lines
The debugging of detecting line changes when pasting continues. There are a number of scenarios that need to be handled and tested. First is the location of where the insertion occurs, which includes at the beginning of a line, in the middle of a line, at the end of the line, and on a blank line (at both the beginning and end of the line). Second is the contents of the text being pasted, which could include a new line at the beginning of the text, a new line at the end of the text and a number of new lines in the text.
While testing these scenarios, a number of issues were discovered when using the delete and backspace key commands when at a blank line including when there is a blank line on the next line (delete at the end of the line) and on the previous line (backspace at the beginning of the line).
In the case of a backspace at the beginning of a line when the previous line is blank, the current line was being reported as deleted, and the previous line was being set as modified (reported as changed when the cursor leaves the line). However, if the current line hasn't been modified, the previous (blank) line only should be reported as deleted. If the current line is modified, again the previous line should be reported as deleted and the current line should remain as modified.
In the case of a delete at the end of the line when the next line is blank, the next line was reported as being deleted and the current line was being set as modified. However, if the current line hasn't been modified and the next line is blank, nothing was actually modified, so it should not have been set as modified.
[commit a3fbc19266]
While testing these scenarios, a number of issues were discovered when using the delete and backspace key commands when at a blank line including when there is a blank line on the next line (delete at the end of the line) and on the previous line (backspace at the beginning of the line).
In the case of a backspace at the beginning of a line when the previous line is blank, the current line was being reported as deleted, and the previous line was being set as modified (reported as changed when the cursor leaves the line). However, if the current line hasn't been modified, the previous (blank) line only should be reported as deleted. If the current line is modified, again the previous line should be reported as deleted and the current line should remain as modified.
In the case of a delete at the end of the line when the next line is blank, the next line was reported as being deleted and the current line was being set as modified. However, if the current line hasn't been modified and the next line is blank, nothing was actually modified, so it should not have been set as modified.
[commit a3fbc19266]
Sunday, February 3, 2013
Two Issues (Connection/Backspace)
While testing the detection of inserted lines when pasting, two issues were discovered. The first was a minor problem where a "connect: no such slot" warning was reported by Qt with the slot that catches the document block (line) count change signal. When this slot function was copied from the Code Editor Example in the documentation, the argument for the number of blocks was removed since it wasn't being used. However, the argument type in the connect call was not changed causing the warning. The argument type was removed from the connect call (it is acceptable to connect a signal with arguments to a slot with no arguments).
The other issue was when using backspace at the beginning of the line, which combines the current line with the previous line. If the current line was marked as modified with a line inserted type (because it is a new line that hasn't been reported yet), then the backspace would report that this line is deleted. However, no line was actually inserted yet, so the next line would have been incorrectly deleted.
To correct this error, backspace now checks for the line inserted modification type and clears the line modified variable and sets the modification type back to line changed instead of emitting that the line was deleted.
One additional issue with this change is that if the current line being combined is blank, then the previous line is not actually modified, so the modified line variable should not be set. To prevent it from getting set, the ignore change flag is set, but then another issue was found.
For some reason, for the delete and backspace key commands, the document change signal is sent twice, which defeated the ignore change mechanism because the document change slot cleared this flag when set. Therefore, instead of clearing this flag in this slot, it is now the setter of this flag's responsibility to clear the flag after the call is made that will trigger the document change signal (the undo and redo functions were already doing this).
[commit 4a2e5f51a7] [commit aa906ee7f4]
The other issue was when using backspace at the beginning of the line, which combines the current line with the previous line. If the current line was marked as modified with a line inserted type (because it is a new line that hasn't been reported yet), then the backspace would report that this line is deleted. However, no line was actually inserted yet, so the next line would have been incorrectly deleted.
To correct this error, backspace now checks for the line inserted modification type and clears the line modified variable and sets the modification type back to line changed instead of emitting that the line was deleted.
One additional issue with this change is that if the current line being combined is blank, then the previous line is not actually modified, so the modified line variable should not be set. To prevent it from getting set, the ignore change flag is set, but then another issue was found.
For some reason, for the delete and backspace key commands, the document change signal is sent twice, which defeated the ignore change mechanism because the document change slot cleared this flag when set. Therefore, instead of clearing this flag in this slot, it is now the setter of this flag's responsibility to clear the flag after the call is made that will trigger the document change signal (the undo and redo functions were already doing this).
[commit 4a2e5f51a7] [commit aa906ee7f4]
Saturday, February 2, 2013
Deleted Lines From Selections (Actions)
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]
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]
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]
Wednesday, January 30, 2013
Catching Line Changes (Combining Lines)
There are two key commands that can cause a line to be deleted (but there is currently no key command to delete a line). One is deleting when the cursor is at the end of the line, where the current line will be combined with the next, the next line will be deleted. The other is backspacing when the cursor is at the beginning of the line, where the current line will be deleted, but the contents of the line will be combined with the previous line.
For the delete check, where the cursor is at the end of the line, it can't be at the end of the file (no line will be deleted) and there can't be any text selected (selections will be handled separately). For the backspace check, where the cursor is at the beginning of the line, it can't be at the beginning of the file (nothing to backspace to) and there can't be any text selected.
Both of these will emit the lines deleted signal for one line, delete will send the current line number plus one and backspace will send the current line number. Both of these signals are sent before the actual deletion takes place in the edit box. When the document changed signal is received, the current modified line number will be set (when the cursor leave the line, it will be reported as changed).
[commit 8cf236c8d3]
For the delete check, where the cursor is at the end of the line, it can't be at the end of the file (no line will be deleted) and there can't be any text selected (selections will be handled separately). For the backspace check, where the cursor is at the beginning of the line, it can't be at the beginning of the file (nothing to backspace to) and there can't be any text selected.
Both of these will emit the lines deleted signal for one line, delete will send the current line number plus one and backspace will send the current line number. Both of these signals are sent before the actual deletion takes place in the edit box. When the document changed signal is received, the current modified line number will be set (when the cursor leave the line, it will be reported as changed).
[commit 8cf236c8d3]
Tuesday, January 29, 2013
Separate Program Change Signals
One of the next items to handle are selections of text in the edit box where multiple lines selected may be cut of deleted, or multiple lines may be pasted. A single line change slot, even with a type, is not sufficient to handle a line changed, lines inserted and lines deleted without some involved code.
Therefore, there will be three signals, the current line changed signal (with a number and text of the line), a new lines inserted inserted (with a number and of list of strings of the lines), and a new lines deleted signal (with a number and count of the number of lines).
For now, there is only the line changed signal and lines inserted signal (for one line) and the equivalent slots in MainWindow. The lines deleted signal will be implemented next when lines are combined due to deleting at the end of the line or backspacing at the beginning of the line.
[commit 1226e81ca4]
Therefore, there will be three signals, the current line changed signal (with a number and text of the line), a new lines inserted inserted (with a number and of list of strings of the lines), and a new lines deleted signal (with a number and count of the number of lines).
For now, there is only the line changed signal and lines inserted signal (for one line) and the equivalent slots in MainWindow. The lines deleted signal will be implemented next when lines are combined due to deleting at the end of the line or backspacing at the beginning of the line.
[commit 1226e81ca4]
Monday, January 28, 2013
Catching Line Changes (New Lines)
So far the edit box is catching lines that are modified including newly inserted lines. One of the ways that new lines are inserted is the Return key (at end of the line) or Control+Return key (splitting a line). The edit box needs to indicate that line has been inserted and not modified, so the line changed signal was modified to report the type of change, modified, inserted or deleted. A new function was implemented for inserting a new line into the program called for both Return keys.
When the cursor is at the end of the line, a new blank line will be inserted on the next line. If the current line is not modified, this line does not need to be emitted since it hasn't changed. However, if the line has been modified, it will be emitted as a modified line. For the new blank line, all that needs to be done is the line number recorded and the new modified line type set to inserted. The line will be emitted as a new line when the cursor leaves the line.
When the cursor is in the middle of the line (splitting the line), the line will be emitted since it is being truncated. For the new line, the end part of the line that is now on the new line, the line number is recorded and the new modified line type set to inserted. The line will be emitted as a new line when the cursor leaves the line.
[commit b1db6d29b0]
When the cursor is at the end of the line, a new blank line will be inserted on the next line. If the current line is not modified, this line does not need to be emitted since it hasn't changed. However, if the line has been modified, it will be emitted as a modified line. For the new blank line, all that needs to be done is the line number recorded and the new modified line type set to inserted. The line will be emitted as a new line when the cursor leaves the line.
When the cursor is in the middle of the line (splitting the line), the line will be emitted since it is being truncated. For the new line, the end part of the line that is now on the new line, the line number is recorded and the new modified line type set to inserted. The line will be emitted as a new line when the cursor leaves the line.
[commit b1db6d29b0]
Sunday, January 27, 2013
Catching Line Changes (Undo/Redo)
Detecting modified lines properly with undo and redo required some effort. The undo and redo functions were reimplemented in the EditBox class so that these operations could be controlled. The key press event handler was modified to catch the undo and redo key sequences and to call these reimplemented functions. A new slot was added to catch when a new undo command is added to the undo queue. This was necessary to catch when a line is modified due to an undo command.
To properly detect line changes, there are several things that undo and redo need to keep track of. No changes are detected until the cursor has been moved from the line, so if all the changes are undone, then no line change gets detected. Therefore, the number of changes made to a line are counted, where this count is decremented for an undo and incremented for a redo. Only upon leaving the line does change get detected if this count is not zero.
Once a modified line is detect, if a further undo returns the cursor to the line, each undo is counted, so that when the cursor leaves the line, the modified line (from the undo) gets detected. Any redo operation while the cursor is on the line adjust the line modification count accordingly.
The source code can be studied for exactly the steps required to accomplish this, which consists of various checks throughout. A new line changed signal was added to EditBox, so modified lines are now emitted with the line number. A slot was added to the MainWindow class that is connected to this signal. For now, this slot function simply outputs the modified line number and text to the console.
There is still a problem when undoing entire lines where lines are actually deleted by the undo. These changes will need to be emitted as line deletions. The same signal can be used, but somehow needs to indicate the line is being delete. There are similar issues when two lines are combined (the second line needs to be deleted), or when cutting, pasting or deleting multiple line selections. There also needs to be a way to indicate when new lines are added.
[commit 6112a7ffd8] [commit f941edae59]
To properly detect line changes, there are several things that undo and redo need to keep track of. No changes are detected until the cursor has been moved from the line, so if all the changes are undone, then no line change gets detected. Therefore, the number of changes made to a line are counted, where this count is decremented for an undo and incremented for a redo. Only upon leaving the line does change get detected if this count is not zero.
Once a modified line is detect, if a further undo returns the cursor to the line, each undo is counted, so that when the cursor leaves the line, the modified line (from the undo) gets detected. Any redo operation while the cursor is on the line adjust the line modification count accordingly.
The source code can be studied for exactly the steps required to accomplish this, which consists of various checks throughout. A new line changed signal was added to EditBox, so modified lines are now emitted with the line number. A slot was added to the MainWindow class that is connected to this signal. For now, this slot function simply outputs the modified line number and text to the console.
There is still a problem when undoing entire lines where lines are actually deleted by the undo. These changes will need to be emitted as line deletions. The same signal can be used, but somehow needs to indicate the line is being delete. There are similar issues when two lines are combined (the second line needs to be deleted), or when cutting, pasting or deleting multiple line selections. There also needs to be a way to indicate when new lines are added.
[commit 6112a7ffd8] [commit f941edae59]
Saturday, January 26, 2013
Edit Box – Custom Context Menu
The Undo and Redo commands require extra work to track line changes they cause. These commands need to be intercepted before the operation is performed, because the wrong lines are detected as being changed. There are three ways that these commands are activated, by their actions (Edit menu and tool bar), keys (Control+Z and Control+Y) and from the default context menu of the edit box.
The actions can be caught by reimplementing the undo() and redo() functions in the EditBox class. The keys can be caught by adding checks for the key sequences in the key press event handler. But the context menu can not be caught (at least none that I could find).
Instead of using the default context menu, a custom context menu will be used for EditBox. The necessary actions are already present. A context menu can easily be added either by adding each action individually or creating a list of actions and then adding the list. The later method was used and after adding the actions, plus the desired menu separators, the setContextMenuPolicy() function is used to tell EditBox to use these actions instead of the default context menu. A side benefit of the custom context menu is that the items have the icons assigned to the actions (the default context menu does not display any icons).
[commit f3fe01028e]
The actions can be caught by reimplementing the undo() and redo() functions in the EditBox class. The keys can be caught by adding checks for the key sequences in the key press event handler. But the context menu can not be caught (at least none that I could find).
Instead of using the default context menu, a custom context menu will be used for EditBox. The necessary actions are already present. A context menu can easily be added either by adding each action individually or creating a list of actions and then adding the list. The later method was used and after adding the actions, plus the desired menu separators, the setContextMenuPolicy() function is used to tell EditBox to use these actions instead of the default context menu. A side benefit of the custom context menu is that the items have the icons assigned to the actions (the default context menu does not display any icons).
[commit f3fe01028e]
Friday, January 25, 2013
Catching Line Changes (Part 2)
There are a number of different keys that could change the position of the cursor that needs to check if the line before the movement was modified including Page Up, Page Down, Return (non-insert move to next line), Return (at end of line), Control+Return (insert new line), Left (if at beginning of the line), Right (if at end of the line), Control+Left (if at beginning of the line), Control+Right (if at end of the line), Control+Home (if not at the first line), Control+End (if not at the last line), and the list probably goes on (like simply clicking the mouse on another line). In any case, a lot of keys to check and special conditions for many (line if at beginning of the line).
I realized there was a much easier way to catch these cursor movements by using the cursor position changed signal emitted by QTextEdit. Therefore, this signal was connected to a new cursor moved slot in EditBox. This slot checks if the current line has been modified (value not ‑1) and if this line number is different than the current line number of where the cursor was moved to, then the capture modified line function is called.
However, this conflicted with the current line reporting mechanism, which was previously called before the cursor was moved, but now was being called after the cursor had moved. So instead of getting the current line (block) number from the text cursor, the current line (block) was found by calling the document's findBlockByNumber() function using the line modified variable value.
These changes work for most of the cursor movement commands, but there still some commands that are not handled properly like Undo, Redo, Control+A (Select All) after a modification, delete operations that combine lines (where the line below being joined needs to be treated as a delete line), and operations involving multiple line changes (like cutting a multiple line selection or pasting a block of lines).
[commit 2f0042faff]
I realized there was a much easier way to catch these cursor movements by using the cursor position changed signal emitted by QTextEdit. Therefore, this signal was connected to a new cursor moved slot in EditBox. This slot checks if the current line has been modified (value not ‑1) and if this line number is different than the current line number of where the cursor was moved to, then the capture modified line function is called.
However, this conflicted with the current line reporting mechanism, which was previously called before the cursor was moved, but now was being called after the cursor had moved. So instead of getting the current line (block) number from the text cursor, the current line (block) was found by calling the document's findBlockByNumber() function using the line modified variable value.
These changes work for most of the cursor movement commands, but there still some commands that are not handled properly like Undo, Redo, Control+A (Select All) after a modification, delete operations that combine lines (where the line below being joined needs to be treated as a delete line), and operations involving multiple line changes (like cutting a multiple line selection or pasting a block of lines).
[commit 2f0042faff]
Catching Line Changes (Part 1)
If this was a regular compiler, a plain text editor would be sufficient. The program would be entered, the user would click run, the text would be compiled and then run. However, this is an incremental compiler where each line as it is entered or modified needs to be compiled immediately. Therefore, the edit needs to catch each line as it is entered or modified.
The document (QTextDocument) of the QTextEdit class provides two signals when it has changed, one when any change is made and one with the specific change made by position and number of characters removed or added. Neither of these are sufficient as one has no detail and the other too much detail. What is needed is when a line has been modified and when the cursor has moved away from this line. It is not necessary to compile the line as each character is entered or deleted.
To accomplish this, a new member variable was added to EditBox that will hold the line number of the last line that was modified and will be initialized to ‑1 to indicate no line has been modified. The document's contents changed signal is connected to a new document changed slot in EditBox. Using this variable and slot, the steps for catching line changes are:
There was a minor problem that needed to be corrected. The line modified variable was initialized to ‑1 in the constructor. When a program was loaded, this triggered the contents of the document to changed and this signal was emitted causing it to record line 0 with a change. To correct this, when the document modified flag is reset, the line modified variable was also reset, so a new EditBox function was added to do both of these operations.
Eventually upon loading a program, the entire program will need to be compiled line-by-line. Now that the basic line detection mechanism is working, the detection of additional cursor movements can be implemented.
[commit 2e3e29c6fb]
The document (QTextDocument) of the QTextEdit class provides two signals when it has changed, one when any change is made and one with the specific change made by position and number of characters removed or added. Neither of these are sufficient as one has no detail and the other too much detail. What is needed is when a line has been modified and when the cursor has moved away from this line. It is not necessary to compile the line as each character is entered or deleted.
To accomplish this, a new member variable was added to EditBox that will hold the line number of the last line that was modified and will be initialized to ‑1 to indicate no line has been modified. The document's contents changed signal is connected to a new document changed slot in EditBox. Using this variable and slot, the steps for catching line changes are:
- In the new document changed slot, the current line number that the cursor is at is recorded in the new line modified member variable.
- If there is a request to move the cursor from the current line, the contents of the current line is obtained (which will eventually be compiled).
- The line modified variable will be reset to ‑1.
- The cursor is then moved.
There was a minor problem that needed to be corrected. The line modified variable was initialized to ‑1 in the constructor. When a program was loaded, this triggered the contents of the document to changed and this signal was emitted causing it to record line 0 with a change. To correct this, when the document modified flag is reset, the line modified variable was also reset, so a new EditBox function was added to do both of these operations.
Eventually upon loading a program, the entire program will need to be compiled line-by-line. Now that the basic line detection mechanism is working, the detection of additional cursor movements can be implemented.
[commit 2e3e29c6fb]
Subscribe to:
Posts (Atom)