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]
Saturday, February 2, 2013
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]
Thursday, January 24, 2013
New Return Key Behavior
Now that the edit box has its own key press event handler, the desired behavior of the Return key can be completed. The Return key will only insert a new line if the cursor is at the end of line, except if the line is blank, otherwise it will just move the cursor to the next line. The Control+Return can be used to always insert a new line.
To determine if the cursor is at the end of a non-blank line, the text cursor of the edit box is used. The text cursor holds the position of the cursor and is also used to make selections and to modify the document of the edit box. Since the text cursor will probably by used for many of the new key sequences that will be implemented, a copy of it is obtained at the beginning of the key press event handler. Any changes made to this copy won't show up in the edit box unless the edit box's cursor is updated (the textCursor() access function only returns a copy of the cursor).
The text cursor contains the functions atBlockEnd() and atBlockBegin() for determining if the cursor is at the end or beginning of the line. For a normal text document, blocks are the same as lines. So, if the cursor is not at the end of a block or at the beginning of a block, the cursor is moved to the beginning of the next block using the moveCursor() function with the NextBlock argument. The modified cursor is put back into the edit box and the handler returns.
This created a problem for the Control+Return key code that created a new Return key event. When this event came back to the handler, it went through the at end of block check and was treated as a Return key and only moved to the next line. To correct this, the new event creation code was replaced with a call to the insertText() function of the text cursor with a string containing a new line character. The handler then returns.
[commit 29159082ec]
To determine if the cursor is at the end of a non-blank line, the text cursor of the edit box is used. The text cursor holds the position of the cursor and is also used to make selections and to modify the document of the edit box. Since the text cursor will probably by used for many of the new key sequences that will be implemented, a copy of it is obtained at the beginning of the key press event handler. Any changes made to this copy won't show up in the edit box unless the edit box's cursor is updated (the textCursor() access function only returns a copy of the cursor).
The text cursor contains the functions atBlockEnd() and atBlockBegin() for determining if the cursor is at the end or beginning of the line. For a normal text document, blocks are the same as lines. So, if the cursor is not at the end of a block or at the beginning of a block, the cursor is moved to the beginning of the next block using the moveCursor() function with the NextBlock argument. The modified cursor is put back into the edit box and the handler returns.
This created a problem for the Control+Return key code that created a new Return key event. When this event came back to the handler, it went through the at end of block check and was treated as a Return key and only moved to the next line. To correct this, the new event creation code was replaced with a call to the insertText() function of the text cursor with a string containing a new line character. The handler then returns.
[commit 29159082ec]
Key Press Event Handler
Upon reading up on events, event filters and event handlers, I realized installing an event filter to handle additional key press events was not the best solution. There are actually several levels at which events can be monitored and intercepted and event filters are the third level up.
The lowest level are the specific event handler functions for a widget, each of which handle a specific type of event. The next level is the event handler for a widget that receives all types of events. The third level is any installed event filter for the widget in backwards order of when they were installed. There are several more levels above this that won't be detailed here. The real purpose of event filters is for another class, like a parent widget, to monitor and intercept the events of several widgets.
Therefore, the event filter function was replaced with a key press event handler function. This function will receive only key press events. Instead of an if statement for checking for the Return or Enter keys, a switch statement was used since other keys will need to be handled. Again, if the key is a Control+Return a new unmodified Return key press event is created and posted. Unlike the event filter function, an event handler function just returns. Being at the lowest level, there are no additional routines that will be called for the event. Similar to the event filter, all unprocessed key press events are passed on to the base QTextEdit class key press event handler.
[commit 241fa39814]
The lowest level are the specific event handler functions for a widget, each of which handle a specific type of event. The next level is the event handler for a widget that receives all types of events. The third level is any installed event filter for the widget in backwards order of when they were installed. There are several more levels above this that won't be detailed here. The real purpose of event filters is for another class, like a parent widget, to monitor and intercept the events of several widgets.
Therefore, the event filter function was replaced with a key press event handler function. This function will receive only key press events. Instead of an if statement for checking for the Return or Enter keys, a switch statement was used since other keys will need to be handled. Again, if the key is a Control+Return a new unmodified Return key press event is created and posted. Unlike the event filter function, an event handler function just returns. Being at the lowest level, there are no additional routines that will be called for the event. Similar to the event filter, all unprocessed key press events are passed on to the base QTextEdit class key press event handler.
[commit 241fa39814]
Wednesday, January 23, 2013
Keyboard Event Filter
One of the tasks for the edit box is to intercept keys before they are processed by the QTextEdit base class so that additional programming related keyboard commands can be implemented. This is accomplished by installing a custom event filter function to the widget. An installed event filter is called before the doing the regular event processing. An event filter can be a member of any class and be installed to any widget. Because I don't see a reason not to, the EditBox class was given an event filter and it is installed to itself in the constructor:
The first key to modify is the Return key. For a text editor, the Return key simply inserts a new line. It is desired that a Return key enter the current line into the program (parse, translate, etc.) no matter where on the line the cursor is at. In other words, not to break the line into two lines at the cursor. However, if the cursor is at the end of the line, it will open a new line (insert a blank line) on the next line. To allow a line to be broken into two, the Control+Return key will be used. The Control+Return is ignored by the QTextEdit class. So the first behavior implemented in the new event filter was to treat a Control+Return key as a Return key.
The event filter receives all event types, so the event type is first checked for key press event. The event pointer is then cast to a QKeyEvent so that the specifics of the key press event can be checked starting with if it contains the Return key. Since the Enter key on the numeric keypad is received as a different code, both the Return and Enter values are checked for. Finally the keyboard modifiers (Control, Shift, Alt, etc.) of the key press event is checked for a control modifier.
The Control+Return key needs to be changed to a regular Return to allow the new line insertion to take place, but the key event can't be modified and passed on. Instead, a new key press event is created for a unmodified Return key and this new event is posted by calling the QApplication::postEvent() static function with the edit box instance pointer (this) for the new event. A true is returned to indicate that the Control+Return key event has been processed. If the event was not a key press Control+Return event, the event is passed through to the regular event filter by calling QTextEdit::eventFilter().
[commit cb32f9ab0e]
installEventFilter(this);The argument of this function call is the class containing the event filter, which in this case is the instance itself. The event filter contains an argument of the object receiving the event and the event itself. In this case, since the event filter was only installed for this instance of the edit box, the object will be the instance itself and there is no need to check it.
The first key to modify is the Return key. For a text editor, the Return key simply inserts a new line. It is desired that a Return key enter the current line into the program (parse, translate, etc.) no matter where on the line the cursor is at. In other words, not to break the line into two lines at the cursor. However, if the cursor is at the end of the line, it will open a new line (insert a blank line) on the next line. To allow a line to be broken into two, the Control+Return key will be used. The Control+Return is ignored by the QTextEdit class. So the first behavior implemented in the new event filter was to treat a Control+Return key as a Return key.
The event filter receives all event types, so the event type is first checked for key press event. The event pointer is then cast to a QKeyEvent so that the specifics of the key press event can be checked starting with if it contains the Return key. Since the Enter key on the numeric keypad is received as a different code, both the Return and Enter values are checked for. Finally the keyboard modifiers (Control, Shift, Alt, etc.) of the key press event is checked for a control modifier.
The Control+Return key needs to be changed to a regular Return to allow the new line insertion to take place, but the key event can't be modified and passed on. Instead, a new key press event is created for a unmodified Return key and this new event is posted by calling the QApplication::postEvent() static function with the edit box instance pointer (this) for the new event. A true is returned to indicate that the Control+Return key event has been processed. If the event was not a key press Control+Return event, the event is passed through to the regular event filter by calling QTextEdit::eventFilter().
[commit cb32f9ab0e]
Tuesday, January 22, 2013
Cross-Platform Fixed Width Font
There are several solutions for setting the font in the edit box to a fixed width font, but a cross-platform solution was needed. One solution would be to use a font that is available on both Windows and Linux, for example Courier, but this is not the best looking font, though it is one of the few available on Windows. My current preferred fixed width font is Monospace, but this font is not available on Windows. Attempting to set this font had no effect on Windows, and the default proportional font was used.
After some research, the correct sequence was found to select the Monospace font on Linux and to select an alternate fixed width font on Windows. First the current font is obtained from the QTextEdit base class. The font is set to fixed pitch to indicate the type of font desired if the selected font family is not found. The font family is set to the "Monospace" string and the style hint is set to Monospace. Finally the current font is set to this modified font. This code was put into the EditBox constructor:
[commit 7155b30097]
After some research, the correct sequence was found to select the Monospace font on Linux and to select an alternate fixed width font on Windows. First the current font is obtained from the QTextEdit base class. The font is set to fixed pitch to indicate the type of font desired if the selected font family is not found. The font family is set to the "Monospace" string and the style hint is set to Monospace. Finally the current font is set to this modified font. This code was put into the EditBox constructor:
QFont font = currentFont();On Windows (XP, 7 and 8), this appears to select the Courier New font at a fairly small 8 point font, which doesn't look so good on XP, but better on 7 and 8. The size of the Monospace font on Linux also looks to be an 8 point font. This is good enough for the now and eventually a font selection dialog will be added so that any font and size can be selected.
font.setFixedPitch(true);
font.setFamily("Monospace");
font.setStyleHint(QFont::Monospace);
setCurrentFont(font);
[commit 7155b30097]
Monday, January 21, 2013
Minor Fix
While testing the tagged download archive for release 0.3.1, a warning message from Qt occurred indicating that the window title did not contain a '[*]' placeholder. This was caused by the application loading the last opened file, after which the window modified flag is cleared. This triggers Qt to update the window title, which was not set yet, hence the warning message.
This warning did not occur if a file was specified on the command line. If the application was started with no prior loaded file or recent list, this message also did not occur, but the window title was set to "MainWindow" instead of the correct "Untitled - IBCP" title.
The warning did not occur if the file was specified on the command line because the code called the set current program function with the file specified, which set the window title before the file was loaded. The solution was to also call the set current program function if no file was specified on the command with the current program member variable value, which solved both the warning message problem and the "MainWindow" title problem.
[commit 6410a5318e]
This warning did not occur if a file was specified on the command line. If the application was started with no prior loaded file or recent list, this message also did not occur, but the window title was set to "MainWindow" instead of the correct "Untitled - IBCP" title.
The warning did not occur if the file was specified on the command line because the code called the set current program function with the file specified, which set the window title before the file was loaded. The solution was to also call the set current program function if no file was specified on the command with the current program member variable value, which solved both the warning message problem and the "MainWindow" title problem.
[commit 6410a5318e]
Edit Box For Program Entry
Now that some additional GUI has been implemented, it is time to start to work on the edit box to make it more appropriate for editing a program and not just text. The immediate goal is to accept BASIC code that is currently recognized by the parser and translator, parse and translate it and display the translation in a dock widget beside the edit box. (A dock widget is a widget that can be moved or docked to any side of the application window or detached completely from the window.)
For an incremental compiler, the application will need to know when a line has been edited (when the user leaves a modified line) so that the line can be recompiled (for now translated), which could be several lines (by a deletion when multiple lines were selected, or a paste of several lines). Also, the font of the edit box needs to be changed to a fixed width font and there needs to be a way to add color, for example, indicating errors and syntax highlighting of BASIC keywords and other program elements.
As seen so far, this will be accomplished with the text cursor that is part of the QTextEdit's document. The document part of QTextEdit is one continuous string of characters, but there is a way to retrieve and replace individual lines within the document. All this needs to be figured out, which will take place over the next several commits.
But first, with additional GUI implemented and working, this is a good place to tag for v0.3.1. The various files (CMake, read me and release notes) were updated for this development release.
[commit a938626ffc]
For an incremental compiler, the application will need to know when a line has been edited (when the user leaves a modified line) so that the line can be recompiled (for now translated), which could be several lines (by a deletion when multiple lines were selected, or a paste of several lines). Also, the font of the edit box needs to be changed to a fixed width font and there needs to be a way to add color, for example, indicating errors and syntax highlighting of BASIC keywords and other program elements.
As seen so far, this will be accomplished with the text cursor that is part of the QTextEdit's document. The document part of QTextEdit is one continuous string of characters, but there is a way to retrieve and replace individual lines within the document. All this needs to be figured out, which will take place over the next several commits.
But first, with additional GUI implemented and working, this is a good place to tag for v0.3.1. The various files (CMake, read me and release notes) were updated for this development release.
[commit a938626ffc]
GUI – Pasting Plain Text
By default, the QTextEdit class that EditBox is derived from accepts rich text (formatted text). The solution for this matter was simply to call the setAcceptRichText() function with false as the argument to prevent pasting rich text. This call was added to the constructor of EditBox.
While adding this to the constructor, it was noticed that the EditBox class was essentially empty, deriving from QTextEdit adding no new functionality. The delete and select all action functions in MainWindow did more that just call a functions in edit box, so this code was moved to new functions in EditBox. Since delete is a reserved name, the delete text function was named remove().
[commit 4050620cae]
While adding this to the constructor, it was noticed that the EditBox class was essentially empty, deriving from QTextEdit adding no new functionality. The delete and select all action functions in MainWindow did more that just call a functions in edit box, so this code was moved to new functions in EditBox. Since delete is a reserved name, the delete text function was named remove().
[commit 4050620cae]
Subscribe to:
Posts (Atom)