Sunday, March 10, 2013

Program View Line Numbers – Custom Item Delegates

It will be very helpful during testing if the program view displayed line numbers like the edit box.  This was accomplished with what Qt calls a custom item delegate.  An item delegate is responsible for drawing the items in a widget and widgets have a default delegate.

A new ProgramLineDelegate class was created with the QItemDelegate class as its base.  Since the program list view is read-only, the only function that needs to be reimplemented in this new class is the paint() function, which has arguments to the painter (used for drawing to the screen), the current style option (which contains information about the view item like its bounding rectangle), and an index of the item to paint.

To start simple, the line number is obtained from the row of the index and the text of the line is obtained from the model of the index (currently the QStringListModel setup to hold the program lines), which is used to get the string of the item that needs to be displayed.  These two items are formatted using the string "%1: %2" to put the line number followed by a colon and the string of the program line.  This string is then drawn to the screen using the painter's drawText() function.

This is crude, but was a proof of concept (this is my first time using delegates).  This will be cleaned up next by drawing the line number separately in its own rectangle with a different background color.  It will also need to determine the width of this rectangle based on the maximum line number like with the edit box.

[commit 941b1f8e75]

Loading File and New File Issues

While testing with the new program view, when doing a File/New, the last line in the document remained in the program and the line was set modified.  With New, the entire program should be cleared.  Further testing revealed additional problems when loading a new file replacing the current file where the lines in the old file were not being removed before the new file's lines were inserted.

Some additional checks were needed to properly handle these situations, which occur when the document is empty.  If the cursor move failed (which occurs when the file is emptied either with a New or before a new file is loaded), if the change indicates one character was added (occurs with the first of two change signals), then a New operation is occurring.  The modified line variable is set to -2 to indicate that a New is in progress so that when the second signal is processed, the code knows if it is due to a New and not a file load.  Otherwise, if the current line count is zero (the document was empty before the change), then this is the first signal of a file load and should be ignored.

When the document is empty and neither of these conditions exist, then all of the document contents were removed, either because a new file is being loaded, a New was selected, or all of the characters were deleted (for example, with repeated deletes or Selected All and Delete).  For the first two situations, all of the lines of the program should be reported as deleted, but for the third, the last line should remain and be set as the modified line.  The load file conditional occurs when the cursor move failed and the New previously set the modified line to -2.  For these conditions, the net line count is set to the number of lines that were in the document, the new line count is set 0 and the change at the beginning of the line flag is set because it is not set when the document is empty.

At the end of the document change routine where the modified line is set to the current cursor line (the end of the change), it needs to instead be set to -1 if it currently set to a -2 from a New operation, so that the first (and only) line in the document after a New operation is not marked as modified.

One other minor problem was also discovered when an empty file is loaded and the document was previously not empty.  The window modified flag was set (shown with an asterisk after the file name in the window title bar).  I'm not sure why this occurs, but it was corrected by clearing the window modified flag after a program is loaded and the document is set.  Reseting the edit box document's modified flag was not sufficient.

Finally, it was noticed that the program view list widget was grabbing focus when a new file was loaded or New was selected as evidenced by the edit box cursor disappearing and the focus could be seen be the light blue focus indicator around the widget.  This list view widget was prevented from grabber focus by setting its focusPolicy property to NoFocus.

[commit 65bd6a9233]