Friday, March 8, 2013

Save Action Enabling

There is a feature in LibreOffice where the save action (menu and tool bar) is only enabled when the document has been modified, otherwise it is disabled.  Microsoft Office does not have this feature.  This feature was simple to add and only required the edit box's document's modification changed signal to be connected to the save action's enabled slot.

[commit 93c856dcb4]

Select All Correction

While testing, it was noticed that when using the Select All (Control+A) key sequence to select the entire document, a cursor position change signal was not being received.  The prevented a line changed signal from being emitted if the current line was modified.  The cursor should be moved to the end of the document.  Using Select All from either the Edit menu or the context menu did work correctly.  This problem was corrected by intercepting the Select All key sequence and calling the select all function that was connected to the menu actions.

[commit 6a7c9c57e4]

Detecting Changes With Undo/Redo

Curiously, when the document's contents change signal is received for an undo or redo operation, the cursor has not been moved yet, so the current cursor position cannot be used to determine the number of lines changed from its line number and whether the cursor is now at the end of the line.

The beginning of the document changed slot function was modified to get the current text cursor and set its position to the position of the change.  The line number of this position and whether this position is at the beginning of the line is obtained.  This cursor is then moved to the end of the change by moving the cursor right by the number of characters added by the change.  This method also works for all of the other types of document changes.  Several of the local variables in the function were renamed to make the code clearer.

The reimplemented undo and redo functions are no longer deleted and were removed along with the checks for the undo and redo key sequences in the key press event handler.  It is also no longer necessary to keep track of the undo and redo operations on the current modified line, so the undo added slot was removed along with the modified line count and undo active variables.  This mechanism was originally implemented to keep track of changes on the current line so that unnecessary line change signals were not emitted, but now the receiver of this signal is will be responsible for detecting actual line changes (see post on March 3).

[commit a9db922c4d]

Before Selection Not Needed

Previously, information about the selection before a document change operation was saved.  This information was used to figure out what text was replaced by the operation.  This is no longer needed because this information can be determined from the position received in the document's contents change signal and from the current cursor position, which is at the end of the change.

Therefore, the before selection no longer needs to be saved.  Also, since this was the only use of the Selection class, this class was also removed.

[commit ebffb4445c]

Thursday, March 7, 2013

Adjusting/Correcting Return Key Behavior

Previously, a Return key only inserted a new line when the cursor was at the end of a non-blank line.  Otherwise, the cursor is moved to the beginning of the next line.  This will reduce accidentally breaking lines in the middle of them.  The Control+Return key was implemented to insert a new line always.  Upon, using the edit box for a while, I decided to make Return insert a new line when on a blank line.

A problem was corrected when there was a selection, a Return key ignored the selection an moved to the next line instead of replacing the selection.  The code was changed to only move to the next line when there is no selection.

There was also a problem when a selection went across two lines, with part of the second line selected.  A Control+Return key entered should replace the selected text with a new line, which it did, however, the edit box contents were no redrawn properly where the selected characters on the second line remained selected on the screen.  These characters were not actually selected and the were deleted from the document.  Must be some sort of bug in the Qt libraries or the libraries routines were not being utilized correctly.

This problem was corrected by replacing the insert text call of a new line with the creation of a new key press event with a Return key, calling the QPlainTextEdit base class key press event handler, deleting the key press event and returning.

[commit a8b9f09778]

Wednesday, March 6, 2013

Issues With Newly Inserted Lines

The edit box contains a variable to indicate when a line has been inserted but not yet reported as being inserted (in other words, a new line).  Lines are not reported as being modified (changed) until the cursor leaves the line.  This will prevent unnecessary compiling of the line as it is being entered.  This includes a new line that is being entered.  There were some issues with new lines that were corrected.

A new line can only occur when multiple lines have changed or a single line has changed and the change is not at the beginning of a line.  After a change, the modified line is marked as new if there was a single line change and the change was not at the beginning of a line or if the cursor is at the end of a line.  The problem was with this last part when the change was due to a delete at the end of a line and the next line was blank (the cursor was still at the end of the line).  This was corrected by checking if characters were added by the change.

When on a new line, if a backspace occurs is entered the beginning of the line or a delete at the end of the line, the current line or the next line was being reported as deleted, but a new line wasn't reported as inserted yet.  This was corrected by adding a check if the current line is modified and new, to reset the status of the line to just modified, and to not report the line that is removed as deleted.  This change caused another minor problem where an empty lines changed signal was emitted (no changed, deleted or inserted lines), so this empty signal was prevented.

The variable being used to indicate whether a modified line was changed or inserted (new) was an enumeration, however, this enumeration only had two values.  To make the code easier to read, the variable was renamed and changed to a boolean variable.

Finally, deleted lines were not always reported correctly in the main window's program changed slot that is temporarily connected to the lines changed signal for debugging.  The deleted lines loop was corrected so that these lines are reported correctly.

[commit f10eca50ba] [commit 4364d7447f] [commit 74a5eb93a0] [commit 53bf17fda2]

Monday, March 4, 2013

New Line Change Detection – Backspace

A check for the backspace key was originally added to catch the situation where a backspace at the beginning of a line combines the line with the previous line, causing the current line to be deleted.  There were a number of conditions that needed to handled that eventually the functionality was put into a separate function (for details, see posts on January 30, February 3, February 6, February 7, and February 9).

The document changed slot function now handles this backspace operation, so the backspace key no longer needs to be checked for and the backspace function was removed.  However, there is a situation with the backspace that is not yet being handled correctly (that was by the backspace function), specifically if a backspace at the beginning of the line occurs on a line currently marked as a new line not yet inserted.  The line is currently reported as being deleted (but was not yet actually inserted).

There are a number of other situations where the modified line is marked as inserted that are not being handled properly by the document changed function.  One case, this function is incorrectly marking the line as newly inserted if the cursor is at the end of the line after the document change.  This is correct only for some situations.  These issues will be addressed next.

[commit 9b1d127f93]

Sunday, March 3, 2013

New Line Change Detection – Inserting Text

The insert text function of the edit box was implemented to process text inserted into the program so that changed lines could be detected and reported.  It was used to insert a new line, for the return key, the reimplemented pasted function, and the paste selection function (middle-click paste on Linux).  This function is not longer needed and was removed.  The code for the return key was already changed to simply use the insert text function of the text cursor (and the document change function handles the line change detection).

The other two uses were also updated starting with the reimplemented paste function originally necessary to catch the paste action (menu, context menu, and tool bar) and call the insert text function.  The paste function is no longer necessary since the document change slot function will be called for all paste operations.  Therefore the reimplemented paste function was removed.  The check for the paste key sequence is also no longer necessary (will be handled by the plain text edit base class key event handle, which will call the document change slot function).

The mouse release event handler was reimplemented in the edit box class to catch the middle-click paste of the selection and call the insert text function.  This is also no longer necessary, so the handler function was removed.  However, the paste selection function, which was called from the mouse release event handler, is also called for the Control+Shift+Insert key sequence to pasting the selection.  This is still needed, so the insert text function call was replaced with the text cursor insert text function.

[commit 361f10a7f5]

New Line Change Detection Code

Detecting all line changes can be performed by connecting to the edit box document's contents change signal that includes the position in the document of the change along with the number of characters removed and added.  Previously, only the number of character values were being saved for the various detection routines and the position was ignored.  However, the position can be used along with some additional information, to fully detect what has changed in the document, and it turns out the number of characters values no longer need to be stored.

One piece of additional information needed is the net change in the number of lines of the document, which can be used to indicate whether lines were inserted or deleted.  Therefore, a new total line count variable was added to the edit box class and updated after processing a contents change signal.  Other information used is if the position of the change was at the beginning of the line and if the cursor is at the end of the line after the change.

The three signals emitted from the edit box for program changes (line changed, lines inserted and lines deleted) were replaced with a single lines changed signal that includes the line number of the change, the number of lines deleted (could be zero), the number of lines inserted (could be zero) and a list of strings of the lines that were changed (if any) and inserted (if any).  The number of lines changed is the size of this list minus the number of lines inserted.

One of the things the new detection code does not do that the old code attempted to do was determine whether a line actually changed or not, and if not it is not reported.  For example, inserted text that started with a new line inserted at the end of a line, the line is not actually modified so it wasn't reported.  Since the new code does not do this, the receiver of the lines changed signal, will perform this check to see if a particular line was actually changed (to prevent the line from being recompiled).

The new line change detection code is mostly fully working, however, it is not completely hooked up to all the possible document changes that can occur.  In some cases, the code was simply modified to compile, so some code was temporarily commented instead of being changed.  In other cases, the code was modified like the capture deleted lines routine was not needed and was removed.  All of the other causes of changes will be hooked and the code will be cleaned up over the next set of commits.

[commit 00dfbe3268]

Monday, February 25, 2013

Detecting Line Changes – New Idea

After some additional research, I discovered what may be a better and easier way to detect line changes (including deleted and inserted line).  The contents change signal that is emitted containing the number of characters removed and added also contains the position in the document where the change occurred.

Since all document changes cause this signal, catching line changes from this signal should be sufficient for all of the commands that change the document including the undo and redo commands.  And it may not be necessary to consider the what text was selected before the change or what the text being inserted contains.

This position of this signal can be used to determine where the cursor was before the change occurred and the line number for this position can easily be obtained and compared to the current cursor line number to determine the number of lines affected by the change.  Along with this position and the current cursor position, the net change in the number of lines in document can be used to determine how many lines may have been deleted or inserted by the command.

While doing initial testing this new scheme, it was noticed that when the file is loaded upon startup (or from loading a file), that two of these contents change signals are emitted along with the general document changed signal (used to catch when a line is modified).  These signals should be ignored.

To accomplish this, the setPlainText() was reimplemented in the EditBox class, which simply sets the ignore change flag, calls the base QPlainTextEdit::setPlainText() function and then clears the flag.  It was also necessary to add a check of this flag in the document changed slot for receiving the contents change signal.

[commit 01d1156c64]

Sunday, February 24, 2013

Pasting Over A Selection (Status)

Getting the modified lines reported correctly when pasting text over a selection is proving to be very difficult.  There are several conditions to check including whether the start of the selection is at the beginning of the line, end of the line, both (on a blank line), or neither (middle of the line); the same for the end of the selection; the number of new lines in the text being inserted, and if the text being inserted starts with or ends with a new line.

These conditions are using to determine the starting line and number of lines (if any) to report as being deleted, if the line that start position is at should be reported as modified, not modified, be included with the deleted lines or the inserted lines, the lines that have been inserted, and if the line the cursor ends up on is modified, not modified or should be marked as a new line to be inserted.

Some of the if statements for these checks are five to eight lines long.  I already know how to simplify if statements for up to four conditions using Karnaugh Maps, but I had to learn how to do ones with five and six conditions (not easy) and gets worst with more conditions.  So I'm going to take a step back and see if there is an easier what handle all this...

Saturday, February 16, 2013

Another Deleted Line Detection Issue

Another issue was found in the capture deleted lines routine when the selection is replaced by a single character (typing a character when text is selected).  There were two conditions that reset the modified line variable when a selection was deleted - when both the selection start and end positions were either at the beginning of a line or at the end of the line.

However, if the selection is replaced with a single character, the modified line variable should not be reset since the line has been modified by the additional of the character.  So a check was added that the number of characters added from the document change must be zero.  This value was already available because it was stored when the document change signal was received (and up to now, was not being used).

[commit 5abae096ce]

Deleted Line Detection Issues

While testing the changes for detecting changed lines when a pasting text over a selection, some problems were found with the proper reporting of lines that were deleted.  The problem was in the existing capture deleted lines routine, not in the new changes.

This routine was simply reporting lines being deleted from the line of the selection start position, for the number of lines in the selection minus one (the remaining line was set as modified).  This did not take into account if the selection start or end position was at the begin or end of their respective lines.  There are situations where the first line of the selection should not be reported as deleted (for instance, if the selection start is not at the beginning of the line, then the line will not be deleted, only modified).

Two checks needed to be made - the first line reported as deleted, and if the line the cursor is on after the deletion will be modified by the delete operation.  For instance, if the selection starts at the end of the line, and the selection end is on a blank line, then the final cursor line after the deletion will not have been modified.

The first line to report as deleted will be the line the selection start position is at unless the selection start position is not at the begin of the line or at the end of the line and the selection end position is not at the begin of the line, in which case, the first line to report is the next line after the start position line.

The delete operation will cause the line the cursor is at afterward to be marked as modified via the document changed signal.  The modified line variable needs to be reset if the line is not actually modified by the delete operation.  This condition is if the selection start and end positions are at the begin of their lines, or if both are at the end of their lines.

As before, if the selection start and end are on the same line, no lines are reported as being deleted.  The Selection class was modified to also be able to report if the selection start and end positions are at the begin or end of their lines.

[commit c753fd1662]

Wednesday, February 13, 2013

Insert Issue And Overwrite Mode

While testing the changes for detecting changed (deleted and inserted) lines when pasting text over a current selection, I noticed that the Shift+Insert sequence, while inserted text from the clipboard, was not being intercepted by the reimplemented paste function.  This was because the key press event handler was only looking for the standard paste key sequence, which is only the Control+V sequence.  So the Insert key code case was modified to look for Shift+Insert sequence in addition to the Control+Shift+Insert sequence.

It was also noticed that just the Insert key was not changing the edit box to overwrite mode from insert mode, which turned out simply to be that the QPlainTextEdit class does not support this by default.  It does support an overwrite mode, so this feature was implemented by using the setOverwrite() function with the argument of the inverse of the current overwrite mode, which causes Insert key (with no key modifiers) to toggle between overwrite and insert modes.

[commit ed503cb558] [commit 0742f7e78d]

Monday, February 11, 2013

Selection Paste Enhancements

When pasting the selection, the cursor position should be changed to the location where the mouse is pointing when the middle mouse button is released not where the current text cursor is located.  The event received in the mouse release event handler contains the position of the mouse relative to the widget (in this case the edit box).

The mouse position is passed to the cursorForPosition() function of the QPlainTextEdit base class to obtain a text cursor for the this position.  The edit box text cursor is then set to this text cursor to move the cursor, so when the selection is pasted, the text will be inserted to where the mouse was pointing.

It is also nice to be able to paste the current selection using a key command.  The Control+Shift+Insert key sequence was chosen.  Shift+Insert is the key sequence is used to paste the contents of the clipboard.  A case was added to the key press event handler key code switch for the Insert key, which checks for the Control and Shift key modifiers.

Since middle mouse button and Control+Shift+Insert needed to do the same thing, a paste selection function was implemented from parts of the mouse release event handler, which gets the clipboard for the application, checks if the selection is supported, sets the text cursor position to the mouse location, gets the text for the selection and inserts the text.  The function returns true if the selection was pasted, and false if the selection is not supported.

Since the position is only set with the middle mouse button, the paste selection function contains a position argument, which defaults to a null point.  The text cursor is only set to this position when the position is not a null point.  Only the mouse release event handler passes the position of the mouse (from the event).

It was also noticed that the backspace key code check in the key press event handler was in the default section of the switch statement that handled the key sequences.  The backspace check was removed and a backspace key code case was added to the switch.

Next Work: Handling the pasting of text when there is current selection text in the edit box, where the inserted text will replace the selection.  This handling will need to detect how many if any lines needed to be reported as being deleted, before reporting the changed and inserted lines from the paste.

[commit addb4fd6eb] [commit 6af5c59191]

Sunday, February 10, 2013

Pasting Selection With Middle-Click

There is another type of paste operation that is supported on Linux, specifically by the X11 window system used by Linux and MAC-OS.  The selection is made using the mouse by clicking at the start of the text and dragging to the end of the text.  This selection can then be pasted into any window using the middle mouse button (the button under the wheel on most modern mice).  Windows does not support this feature.

This paste operation is intercepted by reimplementing the mouse release event handler.  If the event has the middle mouse button, the clipboard is checked to see if it supports this type of selection.  If it does, the text() function is again used to obtain the text of the selection, however, instead of using the default argument (nothing), the QClipboard::Selection argument is used to get this selection text instead of the normal clipboard paste buffer text.  Otherwise, the mouse release event is passed to the mouse release event handler of the QPlainTextEdit base class.

There is one issue with this paste operation however.  The text is pasted at the current location of the text cursor, not where the mouse cursor is actually pointing to at the time of the middle button click.  This will be the subject of next post.

[commit 9d1c0780e8]