Monday, January 21, 2013

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]

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]

Sunday, January 20, 2013

GUI – Edit Actions – Tool Bar

Adding the actions (icons) to the tool bar was simply a matter of dragging the actions from the Action Editor at the bottom of Designer to the tool bar.  Separators were added between the file actions and the cut, copy, paste and delete actions and the undo and redo actions.

While testing the edit actions, it was noticed that the edit box currently accepts formatted text with the paste action (for example, copying an italicized word from a word processor and pasting it into the program).  This will be corrected in the next commit.

[commit 24c21711b9]

GUI – Edit Actions - Enabling

For enabling the undo and redo actions, there are signals from the edit box (derived from the QTextEdit class) when the undo or redo availability changes.  Likewise, there is a signal for when the copy selection availability changes.  The undo, redo, cut, copy and delete actions were set to disabled in Designer.

The edit box's undo and redo signals are connected to the undo and redo set enabled slot respectively.  When an undo or redo is available, this signal is emitted to the action with a true value, which enables the action.  Likewise when an undo or redo is no longer available, this signal is emitted to the action with a false value, which disables the action.

The edit box's copy available signal is connected to the cut, copy and delete set enabled slot.  The copy available simply means that text has been selected, which can then be copied, but also cut or deleted.

[commit d9a3f3b0b7]

GUI – Edit Menu - Actions

The edit box already has a context (right-click) menu with Undo, Redo, Cut, Copy, Paste, Delete and Select All.  Applications customarily also have these same actions on the Edit menu and on the tool bar.  These actions were created in Designer after adding the Edit menu and adding each of these edit actions.  Once the actions were created, each was edited to add an icon, shortcut key and status tip.

The slot functions for each action was implemented in the MainWindow class with the names on_actionName_triggered so that these would automatically be connected to the actions.  The implementation of most of these functions was a single line that calls the appropriate member function of the EditBox instance (undo, redo, cut, copy, and paste).  The delete and select all actions required slightly different handling.

For delete, there is no function to delete the currently selected text in the QTextEdit class that EditBox is derived from.  The QTextCursor member of QTextEdit, which controls the cursor and selection of QTextEdit, must be used.  The textCursor() access function is used to obtain the text cursor of EditBox.  For deleting the current selected, the removeSelectText() function of QTextCursor is called:
m_editBox->textCursor().removeSelectedText();
The select all action required a little more handling.  The QTextCursor has a way of selecting text by using the select() function with an argument to specify what to select, with QTextCursor::Document being the option for selecting all of the text.  However, the select() function can't be called directly using the textCursor() access function like with delete because the selection doesn't get back to the document inside the edit box.  Instead, the text cursor needs to be obtained, the selection made and the text cursor put back with the setTextCursor() access function:
QTextCursor textCursor = m_editBox->textCursor();
textCursor.select(QTextCursor::Document);
m_editBox->setTextCursor(textCursor);
Additional functionality is required to enable and disable these actions when appropriate.  For example, cut and copy should only be enabled if text is currently selected.  The context menu already works like this.  This functionality will be the subject of the next commit.

[commit d8c2933481]

GUI – Recent Files List – Status Tips

I realized that no status tips were given to the open recent menu actions.  Therefore a status tip was added for the Clear Recent List action in Designer.  Sub-menu actions can not be given status tips (they can be assigned, but they don't show up when hovering over the sub-menu because the sub-menu is opened).

Status tips were also assigned to each of the open recent file actions added to the sub-menu with a string that simply says "Open" followed by the full path of the file name.

The code was also changed to use the QstringList::at() function to access the files in the file list member variable instead of using the [] operator.  The reason is that the at() function is more efficient because the [] operator returns a modifiable reference to the item (an lvalue), where as the at() function just returns a reference (an rvalue).

[commit 858bbe1e28]

GUI – Current Directory

While the application is running, it will remember the directory of the last file loaded so when the open file dialog is displayed again, that directory will be the starting directory.  This application's current working directory is updated by the open file dialog after a file is selected.  A "." for the current directory is used as the starting directory passed to the open file dialog box, so when the application is restarted, the current directory starts back to where the application was started from.  The application should remember the last directory when restarted.

To have the application remember the last directory, a new current directory member variable was added to the MainWindow class.  After a new file is loaded from the Open menu action, the directory of the file path is saved in this variable.  This variable is then saved as part of the application settings and restored when the application is started.

As was done for the restore and save settings for the RecentFiles source file, the names of the settings were put into constant character strings so that the strings are not specified in two different places (the restore and save functions) to prevent the possibility of a mistake in the name between the two functions, which would cause a setting to not be restored properly.

[commit 04c28a8252]

Saturday, January 19, 2013

GUI – Recent Files List

The next GUI feature implemented is a recent programs list, which consists of a new Open Recent sub-menu item on the File menu below the Open menu item.  This sub-menu contains a list of recent programs along with a separator and a Clear Recent List menu item.  The Open Recent menu item is disabled if there are not recent files.  Files are added to the recent list when opened or when the Save As... menu item is used.

New files are inserted at the top of the list, pushing older programs down the list.  Currently only 4 programs are listed in the list (this will be made configurable later), but up to a  maximum of 10 recent programs are kept in the list.  When a new program is added to the list, any existing entry of the program in the list is removed first and any files above the maximum count are removed.

A new RecentFiles class was implemented to maintain this list of recent files and the Open Recent sub-menu actions.  When instanced, the open recent file actions are created for the maximum number of files, sets each to invisible, sets its icon to the file open icon and connects their triggered signal to an open file slot (which does not occur automatically like when menu actions are added in Designer).  The open recent file actions are inserted before the first existing action in the menu, which is assumed to contain a separator and the Clear Recent List actions (added in Designer).

The RecentFiles class contains public functions for adding a file to the recent list, clearing the list, restoring the list (and count) from the saved application settings, and saving the list (and count) to the application settings.  When one of the recent file menu actions is triggered, an open file signal is emitted.  When MainWindow instances this class, it connects this signal to a new program open slot function.

The RecentFiles class contains two private support functions.  One to update the actions on the sub-menu list, which first removes any files in the list that don't exist, and then scans the list setting the open recent file menu action's text and data to the base name of the file path and its full path, and makes it visible.  Any actions above the current count or the number of files present are set invisible.  The second is a simple support function for returning the base file name of a path.

[commit bf8cda57eb]

Tuesday, January 1, 2013

GUI – Program File Argument

The next feature added is the ability to specify a program file to load on the command line.  This is specifically to support integrating the application with the OS where files with a certain extension can be associated with the application.

The CommandLine class was modified to look for a single argument that does not begin with a "-" option character if none of the other expected options were found.  This argument is stored into a new file name member variable, which has an access function to get its value.  The usage help message was updated for the new argument.

The MainWindow constructor was modified to check if the file name from the CommandLine instance is not empty.  If it is not empty, then the current program is set to this file name overriding any in the saved settings.  If this program doesn't exist or there is an error loading the program, then the application starts up blank but with the current program name set to the file specified instead of being Untitled.

[commit c8f48aa9d5]

GUI – Save Current Program

Now, that the basic GUI elements are in place, some additional features will be added before beginning work in changing the edit box from a simple text editor into a program editor.  The first feature to add is to have the application save the program file path name that was loaded the last time it was run.  This involves saving the current program path as part of the saved settings.

When the settings are restored, the set current program helper function is called with the restored program name.  The current program member variable can't be set directly because the window title does not get set and a warning message is issued by the Qt routines that there is no '[*]' placeholder in the window title when the program is loaded.  When the program is loaded into the edit box, a document modified signal is sent to the set window modified slot, when then attempts to set the modified flag, but placeholder has not yet been set in the window title.  The helper function takes care of this.

Once the edit box instance has been created, the constructor checks if the current program is not empty.  It then checks if the program file still exists, otherwise the file was either deleted or moved since the last run, so the current program path is cleared.  Also, if there is an error loading the program file, the current program path is cleared.

[commit dd489476cc]

Base GUI Complete

All the basic GUI elements have now been added, so this is a good place to tag the release, which was tagged with the name v0.3.0.  The various files (license, read me, release notes, etc.) were updated for this development release.

It was also noticed the about box (nor the test output) contained the full GPL statement, only the copyright and warranty statements.  The CommandLine class was updated to reflect this, but the test output was not changed so that the regression tests continue to pass.  The About box was updated to contain the full GPL statement along with the required Oxygen icons license statement and web links.

The original release numbering is again being used.  While Git did sort the tags as desired with the '-' developmental release before the '.' official release (so v0.2.0 will be listed after v0.2-6); GitHub (on the tags page) appears to only look at the numbers ignoring the separator characters, so v0.2.0 is sorted before v0.2-1 instead of after v0.2-6, which could be very confusing even though a fuzzy time of the release is listed, it's not obvious, and there is no way to sort by this time.

Since all 0.x releases are development releases, there is no reason to have development development releases.  For now on, only the last one of the development release series will be uploaded to Sourceforge, whatever is release number is at that point.  The source code of the others can be downloaded as archives from GitHub on the tags page.  The release number for any patches needed for an official release will simply increment the last (patch) number and re-uploaded.

[commit 4f0378e72c]

Monday, December 31, 2012

GUI – Icons and Tool Bar

Now that the resource mechanism has been added to the project, actions can now be added to the tool bar with appropriate icons.  Contrary to what was said at the beginning of the last post, tool bar items can be text and are text if no icon has been assigned to them.  In any case, icons will be used here for the tool bar.  Also, when an action has an assigned icon, the icon also appears on the menu item in the menus.

First icons need to be assigned to the actions.  The easiest way to do this is with Designer inside QtCreator.  The icons can be assigned the same as with the MainWindow object, but it is easier to add the icons from the Action Editor tab at the bottom of Designer.  Double-clicking on the action brings up the Edit Action dialog.  The icon is added by clicking the ... button on the Icon: field line.  Appropriate icons were added to all of the actions.  To add the actions to the tool bar, the actions are simply dragged from the Action Editor to the tool bar.

Note: The icons will not be available on the
Select Resource dialog until the program has been built after the icons have been added to the resource file.

The icons were obtained from the KDE Oxygen icon set (found in the /usr/share/icons/oxygen/32x32/actions/ directory on Linux) except for the Qt icon, which was obtained from the Qt SDK.  All of the icon file names were renamed to match the menu and menu item the icon was assigned to.  The Oxygen icons can be distributed with the source code and embedded within the program as long as the program is under the LGPL (Lesser GNU Pulbic License) version 3, which this program is being developed under.

[commit a2d2675627]

GUI – Icons and Resources

The next item for the GUI is to add items to the tool bar, which has already been created, but is currently only blank.  Unlike the menu items which are text, the tool bar items are icons.  It is convenient if the icons are part of the application file and not separate files that must be included to run and must be loaded by the application.

This is accomplished by converting the icon files into C++ source files that are then compiled and linked into the application.  The Qt Resource Compiler (RCC) is used to convert the icon files to source files.  All the resources for the program are listed in an XML resource (.qrc) file.  QtCreator makes it easy to create and maintain these resource files.

To create the resource file, the new file wizard was again utilized.  Under Files and Classes the Qt item (lower-left) and Qt Resource file (upper-right) was selected.  On the next Choose the Location dialog, the Name: field was set to ibcp.qrc.  On the next Project Management dialog, the defaults were selected (which was set to git).  Once finished, QtCreator opened up a specific resources editing window.

To start simple, an application icon was given to the program, which will appear in the upper corner of the application window and on the task bar of the OS.  Up to now, a generic icon was being used (an X icon on Linux/KDE and a generic program icon on Windows).  An icon file was created by the name ibcp.png and placed in the new images sub-directory.  The image chosen and created consists of two lightning bolts, which represents the letter I, two to represent Interactive and Incremental, for the type of BASIC compiler being created.  The lightning bolt itself represents speed, since the goal of this project is to make a fast interactive BASIC compiler.

To add this new icon to the resource file, the Add button at the bottom resource editing window was clicked and Add Prefix was selected.  The Prefix: field, which defaulted to /new/prefix1 was cleared (which set it to a single slash).  The Add/Add Files was then selected, which opened a file selection dialog.  The images/ibcp.png file was selected, which added the file to the resource list.

To assign this icon file to the application, in Designer, the MainWindow object was selected (upper-right panel) and under properties (lower-right panel), the ... button was clicked for the windowIcon property, which displayed a Select Resource dialog.  The images item (left-side) was selected, which displayed the ibcp.png icon (right-side), which was selected.

To finish, the building of the resources needed to be added to the CMake build file.  Resources are handled by the qt4_add_resources command that is added as part of the Qt4 CMake module.  This command is given a list of resource files (in this case ibcp.qrc) and produces a list of resource source files that are generated by RCC.  This list of generated source files was then added to the add_executable command.

[commit ba9ee1be2a]

Sunday, December 30, 2012

GUI – Status Bar

The status bar on the bottom of the window was already automatically created when the MainWindow class was created from the new file wizard and is already being used for the menu item status tips.  Eventually program information like current line and column will be displayed on the status line along with error messages.  But for now there are a few places where messages are needed for the file operation functions, specifically when the program has been loaded or saved successfully.

[commit ea1b7585bb]

GUI – File Operations - Functions

A couple of helper functions were implemented to support the file operation functions.  The first is a function check if it is okay to continue, which checks if the file has been modified and if it has, ask if the file should be saved or the operation canceled.  This check is needed on the new, open and close program functions.

The second helper function sets a new member variable that holds the current program file path and sets the window title to the base file name of the current program file path.  The window title is set to the string "<file name>[*] ‑ IBCP" where the [*] is a placeholder for whether the file has been modified.  Qt handles this in a platform specific way.  Qt handles this in a platform specific way.  Generally on Windows and Linux, it  simple puts an asterisk after the file name, but on MAC, a dot is put in the close bubble.  If the program file path is blank, the program name is set to the "Untitled" string.

In the main window constructor, a connection was added to the edit box document's modification changed signal to the main windows set window modified slot.  Whenever the document is modified, this signal causes the file modified indicator to appear.

Two support functions were also implemented that load and save the program into or from memory, though right now they simply read and write a text file to or from the edit box document as plain text.  Eventually when a program is loaded, it will need to be parsed, translated, encoded and stored in memory.  Details of the main file operation functions can be found by clicking Continue...

[commit ea1b7585bb]

Actions/Menus – Using Designer

I discovered a much better and easier way to create actions and menus for the application without having to write all the lines of code by using Designer within QtCreator.  The UI form for the main window is opened in Designer by double-clicking on mainwindow.ui from the project files area.

Main menus are added by double-clicking on the "Type Here" text at the top of the edit area and entering the text.  Hot keys are entered by preceding the desired character with an '&' ampersand character.  The menus can be repositioned by dragging them as desired.

Menu items are added is a similar way, by selecting the main menu and again double-clicking the "Type Here" text.  Separators are added by double-clicking the "Add Separator" text.  Status tips are entered in the statusTip field on the lower-right side properties after selecting the desired action from the upper-right side object tree list.  Shortcut keys can be entered in the shortcut field in the properties area or can be entered using the Action Editor tab at the bottom of Designer.

Designer automatically names the actions with the name "actionXxx" where Xxx is the text entered for the menu item.  The under-bar character is used for spaces, so these were removed to follow the camel casing naming convention.  Qt will make connections between actions and functions automatically if the functions are named correctly.  For the menu item actions, the functions are named on_actionXxx_triggered() where actionXxx is the name of the action and triggered is the name of the signal to connect.  All of the dummy program functions were renamed to this form so that the needed connections are made automatically.

However, this does not work for connecting the actionExit triggered signal to the MainWindow::close() function, since this does not follow the automatic naming convention.  This was accomplished by using Signal & Slots Editor tab at the bottom of Designer.  A new signal/slot is added by clicking the large plus icon.  For this new entry, the Sender was set to actionExit, the Signal was set to triggered(), the Receiver was set to MainWindow, and the Slot was set to close().

The actionAboutQt action could not be setup in Designer since there is no way to connect to the application's aboutQt() function using the Signal & Slots Editor because the application object is not an available Receiver.  This was instead accomplished by adding a new on_actionAboutQt_triggered() function to MainWindow, which simply calls qApp‑>aboutQt().

Now that all the actions and menus are in the UI form for MainWindow, the action enumeration, action pointers and menu pointers were removed from the class definition.  The pointers are now contained in the Ui::MainWindow class that is automatically generated from the mainwindow.ui form file by the UIC (Qt User-Interface Compiler), which MainWindow contains a member pointer to.  Since the setupUi() function, called in the constructor, now creates the actions and sets up the menus, the createActions() and createMenus() functions are no longer needed and were removed.

[commit 46737de13d]