The Qt transition is now complete and the implementation of the GUI can begin. But first this is a good point to make a development release. Release 0.2.0 was made (branch0.2 was merged to the master branch and tagged v0.2.0).
There is one issue when running the program on Windows when starting the program from Explorer. A console window is opened underneath the GUI (About box), which is closed upon exit. This can be removed by adding the WIN32 option to the add_executable command in the CMake build file. However, this causes the command line options to no longer work. This issue will be resolved later.
Archive files containing the source files and binary files (with test files) have been uploaded to SourceForge. For Windows, there is also the ibcp‑libs.zip file that contains all the dynamic linked libraries required to run the program if the MinGW and QtSDK packages have not been installed (extract in the ibcp directory). Linux should already have the required libraries installed.
This concludes the 0.2 development series. Implementation of the GUI elements will now begin with the 0.3 development series.
[commit 85d28cd9e5]
Sunday, December 9, 2012
GUI Preparation – About Box
The about string contains the full name of the program using the HTML header tag for emphasis. As done in the Tester run function, the lines of GPL statement are added next. Instead of putting the program name as the first part of the copyright line, the version string will be used instead with the string "Version" in front of it. For the about box, the tr() function is used to translate the strings. Since this is a preliminary about box, a placeholder for the full GUI, an italicized message stating such is added next. This is followed by the command line usage string (modified to show all the options are optional). An image of the about box running on Windows 7 is shown below.
So that the new about function has access to the GPL statement, version string, copyright year and usage string, the CommandLine instance was made a member variable as a pointer to the MainWindow class instead of being temporary in the constructor. The instance is created in the constructor and deleted in the destructor.
The show() function for the QMainWindow class was temporarily reimplemented in the MainWindow class to prevent the full GUI from appearing (which is currently empty). The reimplemented function calls the about() function and then does a single shot timer connected to the application quit function to end the program once the event process loop is entered. Finally, a check for no command line options was added towards the beginning of the constructor to exit the constructor (which will start the GUI in the main function).
[commit 6eab34398c]
GUI Preparation – Usage String
Since for now the GUI is only going to pop up the About box and then exit, it would be nice if it included some information about how to use the program from the command line, specifically displaying the usage string that was previously output when no arguments were given (which will start the GUI). The CommandLine class was modified to generate the usage string at the beginning of the constructor and save it in a new member variable, with a new function to access it.
Previously, the test options were obtained from the Tester instance, but this isn't created until later in the constructor and won't be created if there are no command line options (the constructor will return). The Tester options access function didn't actually use any instance variables, so this function was made a static member function so that now an instance isn't necessary to access the test options.
[commit 3b93360cff]
Previously, the test options were obtained from the Tester instance, but this isn't created until later in the constructor and won't be created if there are no command line options (the constructor will return). The Tester options access function didn't actually use any instance variables, so this function was made a static member function so that now an instance isn't necessary to access the test options.
[commit 3b93360cff]
GUI Preparation – Version String
One of the items needed in the About box is the version string. Two minor changes were made to the CommandLine class so that it can provide the version string. The previous version() function was renamed to isVersionOption() to mirror the name of the isHelpOption() function.
A new version() function was added to access the version string. The version string is accessed from the ibcp_RELEASE_STRING definition contained in the CMake generated ibcp_config.h header file (from ibcp_config.h.in). CMake gets the release string from either git (if the repository is present) or from variables set in the CMakeLists.txt file. The actual version string starts at the seventh character of release string, which skips over the "release" part of the string.
An include statement could be added to whichever source file needs the release string, but keeping the include in a single source file and providing access functions to its values allows this to be updated in the future without having to change a bunch of other source files. This also applies to the copyright year value. The CommandLine class also provides access to the program name.
[commit 5431b8f9b4]
A new version() function was added to access the version string. The version string is accessed from the ibcp_RELEASE_STRING definition contained in the CMake generated ibcp_config.h header file (from ibcp_config.h.in). CMake gets the release string from either git (if the repository is present) or from variables set in the CMakeLists.txt file. The actual version string starts at the seventh character of release string, which skips over the "release" part of the string.
An include statement could be added to whichever source file needs the release string, but keeping the include in a single source file and providing access functions to its values allows this to be updated in the future without having to change a bunch of other source files. This also applies to the copyright year value. The CommandLine class also provides access to the program name.
[commit 5431b8f9b4]
GUI Preparation – GPL Statement
The lines of the GPL statement was implemented as a QStringList in the CommandLine class. The intention was to use this string untranslated for the test output (so the output matches the expected output files). The QT_TR_NOOP() macro was used on the strings, so that the strings could be found by the Qt translation utilities. The tr() function would be used later (by the GUI's About box), to translate strings (given the program was set up to do translations and the appropriate translation file was available).
However, this is not how the tr() function works. The tr() function takes a constant char pointer and translates the string. It does not accept a QString, so the scheme described above will not work. Therefore, the GPL statement was changed from a QStringList to a const char * array, and also changed from a regular member to a static member. The initialization of which was moved outside of the CommandLine constructor. The variable was also appropriately prefixed with a 's_' to represent a static member.
The first line of the GPL statement requires special handling:
The Tester run function previously received the GPL statement (as a QStringList argument), which it simply output. However, since the statement is now raw character strings, it will need to fill in the first line with the program name and copyright, neither of which it had access to. These could have been added as additional arguments, but instead, the argument was changed to a CommandLine instance pointer, which has new access functions for these values. After converting the GPL line to a QString, if at the first line, the program name and copyright year are filled in.
One other minor problem in the Tester run function was discovered and corrected with the interactive testing mode. The "Testing Xxx..." string was being output before the GPL statement and it should have been after the statement and the "Table initialization successful" message.
[commit c25848a1829] [commit e27358a938]
However, this is not how the tr() function works. The tr() function takes a constant char pointer and translates the string. It does not accept a QString, so the scheme described above will not work. Therefore, the GPL statement was changed from a QStringList to a const char * array, and also changed from a regular member to a static member. The initialization of which was moved outside of the CommandLine constructor. The variable was also appropriately prefixed with a 's_' to represent a static member.
The first line of the GPL statement requires special handling:
"%1 Copyright (c) 2010-%2 Thunder422"Where the %1 and %2 are place holders for the program name and the current copyright year. These were previously filled in by the CommandLine constructor when the QStringList was created. This can only be done after the string is in a QString, in other words, after it has been translated (if it is going to be translated).
The Tester run function previously received the GPL statement (as a QStringList argument), which it simply output. However, since the statement is now raw character strings, it will need to fill in the first line with the program name and copyright, neither of which it had access to. These could have been added as additional arguments, but instead, the argument was changed to a CommandLine instance pointer, which has new access functions for these values. After converting the GPL line to a QString, if at the first line, the program name and copyright year are filled in.
One other minor problem in the Tester run function was discovered and corrected with the interactive testing mode. The "Testing Xxx..." string was being output before the GPL statement and it should have been after the statement and the "Table initialization successful" message.
[commit c25848a1829] [commit e27358a938]
Saturday, December 8, 2012
GUI Preparation
The 0.2 development series is going to conclude with the program displaying its about box and then exiting. The GUI elements will be added in the 0.3 development series. Before adding the about box, some modifications to existing classes are needed, which will occur over the next set of commits. But first, this is probably a good time to create the v0.2-6 tag as there have been 11 commits since the last development tag.
The base GUI is already present in the program, which was added by default when the main window class was created by new class wizard in QtCreator. This GUI only contains a blank menu bar, tool bar and status bar. If it was activated, the only thing present beside the window title (with the normal minimize, maximum, close, etc. icons) would a blank window with an empty tool bar that can be docked (more on this later) on any of the four sides of the window.
However, the program is not currently activating this window because it exits with a usage message if no options were present on the command line. The command line and tester classes need some minor modifications before the about box can be implemented, which will contain information that will be obtained from the command line class (version, GPL statement, etc.).
[commit 6f55c2ffae]
The base GUI is already present in the program, which was added by default when the main window class was created by new class wizard in QtCreator. This GUI only contains a blank menu bar, tool bar and status bar. If it was activated, the only thing present beside the window title (with the normal minimize, maximum, close, etc. icons) would a blank window with an empty tool bar that can be docked (more on this later) on any of the four sides of the window.
However, the program is not currently activating this window because it exits with a usage message if no options were present on the command line. The command line and tester classes need some minor modifications before the about box can be implemented, which will contain information that will be obtained from the command line class (version, GPL statement, etc.).
[commit 6f55c2ffae]
Table Initialization – Revisited
The Table class was modified to be singleton class (see November 14). This implementation was modified. To be consistent with the Token class, which is initialized with a static initialize() function, the Table class create() function was renamed to initialize() and changed to return nothing instead of a list of errors.
The old initialize() function, a normal private member function, was renamed to setupAndCheck() and still returns a list of errors. Two new static functions were added to access the error list: hasErrors() to report if there were any errors detected and errorList() to return the list of errors. Both fatally abort the program if the initialize function was not called. The initialize function stores the error list returned by setupAndCheck() into a new static error list member variable.
The two static members, one for the pointer to the single instance and the other for the error list are now prefixed with 's_' instead of 'm_' to denote a static member as opposed to a regular member variable. The static member variables to the Token class were also renamed with the 's_' prefix.
The new initialize function also checks if either the instance pointer is not null or if the error list is not empty to determine if the table instance was previously created or at least attempted. When an error is found, the instance is deleted, so the instance pointer alone can't be used to determine if the instance creation was attempted. Similarly, the new error list access functions also check if both the instance pointer is null and error list is empty to determine if there was a creation attempt. The check for a non-empty error list was also added to the instance() access function.
The Token and Table initialize function calls were moved from the Tester run function to the main function. This keeps the initialization in a single location. The Tester run function still contains the check for table errors. The error check was not moved to main because when the GUI is started, any table errors need to be reported in an error dialog box, not to the console output. When the program is started from say an OS start menu or file browser, there is no console for these errors and the program will inexplicably fail to start. Now work on the GUI can begin...
[commit 5c5da1f069] [commit e0474f5144]
The old initialize() function, a normal private member function, was renamed to setupAndCheck() and still returns a list of errors. Two new static functions were added to access the error list: hasErrors() to report if there were any errors detected and errorList() to return the list of errors. Both fatally abort the program if the initialize function was not called. The initialize function stores the error list returned by setupAndCheck() into a new static error list member variable.
The two static members, one for the pointer to the single instance and the other for the error list are now prefixed with 's_' instead of 'm_' to denote a static member as opposed to a regular member variable. The static member variables to the Token class were also renamed with the 's_' prefix.
The new initialize function also checks if either the instance pointer is not null or if the error list is not empty to determine if the table instance was previously created or at least attempted. When an error is found, the instance is deleted, so the instance pointer alone can't be used to determine if the instance creation was attempted. Similarly, the new error list access functions also check if both the instance pointer is null and error list is empty to determine if there was a creation attempt. The check for a non-empty error list was also added to the instance() access function.
The Token and Table initialize function calls were moved from the Tester run function to the main function. This keeps the initialization in a single location. The Tester run function still contains the check for table errors. The error check was not moved to main because when the GUI is started, any table errors need to be reported in an error dialog box, not to the console output. When the program is started from say an OS start menu or file browser, there is no console for these errors and the program will inexplicably fail to start. Now work on the GUI can begin...
[commit 5c5da1f069] [commit e0474f5144]
Standard Error Output - Oops
My job took me away from this project the past week. In making the next set of changes, I discovered that the last commit did not compile. During the development of the standard error output changes, the coutClose() function (which closes the current channel if open) was originally named cclose(). At the last moment, this was renamed to the more appropriate coutClose(), but in the haste to get the code committed, the code was not compiled and retested.
It has been recent policy recently make sure every commit pushed to the repository compile and test successfully, at least on the development platform (Linux). Any problems with testing would be noted in the commit message. The last commit failed this policy and I apologize (and worst, it went for a week in this state).
When a development tag is added, it is validated to compile and test successfully on both the Linux and Windows platform (specifically XP, though it should work on 7 also). Again any problems are noted in the commit message. For an actual release however, it will also be tested on the Windows 7 platform (and there should be no test issues).
[commit 4ffed94ea2]
It has been recent policy recently make sure every commit pushed to the repository compile and test successfully, at least on the development platform (Linux). Any problems with testing would be noted in the commit message. The last commit failed this policy and I apologize (and worst, it went for a week in this state).
When a development tag is added, it is validated to compile and test successfully on both the Linux and Windows platform (specifically XP, though it should work on 7 also). Again any problems are noted in the commit message. For an actual release however, it will also be tested on the Windows 7 platform (and there should be no test issues).
[commit 4ffed94ea2]
Saturday, December 1, 2012
Standard Error Output
Command line error messages should be sent to the standard error channel; the Qt qWarning() function should not be used because these messages can be disabled. The cout() function was modified to accept a FILE stream (channel) pointer, either stdout or stderr, with stdout the default. The qWarning() calls were changed to cout(stderr), which made these lines cleaner because the qPrintable() function is not longer needed to output QString values.
There was also a qWarning() call in the Tester run function when table errors are detected. These only occur when there are problems in the table entries and are followed by a qFatal() call (which terminates the program). This qWarning() call was changed to a qCritical() call, whose messages can not be disabled.
Previously, to get the usage message, invalid arguments had to be specified. To get the usage message without returning an error, new help options were added (either '-?' or '-h'). The usage message will be output to standard output channel when using these options, but to the standard error channel for invalid arguments.
When an error occurs in the Tester run function, like when the test file can't be opened, the standard output channel needs to be closed and the standard error channel opened to output the error message. The new function coutClose() was added to the CommandLine class, which closes the current channel (if open), which is called before outputting the error message from the Tester instance. The code for this function was pulled from the destructor, which was replaced with a call to the new function.
[commit e64eadee4a]
There was also a qWarning() call in the Tester run function when table errors are detected. These only occur when there are problems in the table entries and are followed by a qFatal() call (which terminates the program). This qWarning() call was changed to a qCritical() call, whose messages can not be disabled.
Previously, to get the usage message, invalid arguments had to be specified. To get the usage message without returning an error, new help options were added (either '-?' or '-h'). The usage message will be output to standard output channel when using these options, but to the standard error channel for invalid arguments.
When an error occurs in the Tester run function, like when the test file can't be opened, the standard output channel needs to be closed and the standard error channel opened to output the error message. The new function coutClose() was added to the CommandLine class, which closes the current channel (if open), which is called before outputting the error message from the Tester instance. The code for this function was pulled from the destructor, which was replaced with a call to the new function.
[commit e64eadee4a]
Returning Command Line Errors
When the starting of the single shot time to force the application to quit upon entering the event loop was replaced by a simple return (of 0), I realized that it should really be returning an error code if there is an error in the command line options.
To accomplish this, the processed flag in the CommandLine class was replaced with return code variable, which has three values: 0 for successfully processed command line only option, 1 for error occurred with the command line options, and -1 for no command line only options (in other words, start the GUI). An access function was added for the return code.
The processed access function remains (so callers don't need to be modified), but now returns true if the return code variable is not negative. A return code variable was also added to the MainWindow class along with an access function. In the constructor, the return code is obtained from the command line instance when the GUI active flag is set to false (when the command line was processed). The main function was modified to return this code.
By convention, a command returns a code of 0 to indicate success and any other value to indicate an error. Some commands return a specific error code value, but here just a general error occurred code (1) is returned. To test if this new functionality was working correctly, this command was used:
[commit 164fb19fe8]
To accomplish this, the processed flag in the CommandLine class was replaced with return code variable, which has three values: 0 for successfully processed command line only option, 1 for error occurred with the command line options, and -1 for no command line only options (in other words, start the GUI). An access function was added for the return code.
The processed access function remains (so callers don't need to be modified), but now returns true if the return code variable is not negative. A return code variable was also added to the MainWindow class along with an access function. In the constructor, the return code is obtained from the command line instance when the GUI active flag is set to false (when the command line was processed). The main function was modified to return this code.
By convention, a command returns a code of 0 to indicate success and any other value to indicate an error. Some commands return a specific error code value, but here just a general error occurred code (1) is returned. To test if this new functionality was working correctly, this command was used:
ibcp -v && echo no errorThis command will output the version number followed by the "no error" message. If the -v is replaced with an invalid option, the "no error" message will not be output.
[commit 164fb19fe8]
Friday, November 30, 2012
Qt GUI Files and CMake
Previously, new header or source files were added to the list of header and source files in the CMake build file CMakeLists.txt. Qt form files (with the .ui extension) and header files containing the Q_OBJECT macro are handled differently.
The Q_OBJECT macro is added to any class definition that contains Qt's C++ extensions for defining signals and slots, which are class sections in additional to the normal private, public and protected sections. These are handled by Qt's Meta-Object Compiler (moc), which produces a special MOC source file from the header file. For mainwindow.h, the special source file produced is moc_mainwindow.cxx, which then gets compiled and linked into the program.
In the CMake build file, this is handled by the qt4_wrap_cpp command that is added as part of the Qt4 CMake module. It is given a list of MOC source files and produces a list of MOC output source files. This output list is then specified as a dependency to the output executable. When a header file is included in the MOC sources list, it does not also need to be specified in the list of [normal] header files.
Qt form files are generated as an XML like language. This file needs to be converted into a class definition (within a header file) so that it can be used by the C++ code. These conversions are handled by Qt's User Interface Compiler (uic), which produces a special header file from the form file. For mainwindow.ui, the special header file produced is ui_mainwindow.h, which contains the Ui_MainWindow class. This source file is then included by the mainwinow.h header file.
In the CMake build file, this is handled by the qt4_wrap_ui command. It is given a list of form UI files and produces a list of user interface header files. This output list is then specified as a dependency to the output executive.
All of the generated files are placed in the CMake build directory, the same directory where the auto-generated header files (from the awk scripts) are placed. This directory (the project binary directory) is specified in the include_directories command, so that the C++ compiler can find all of these generated files. It is also no longer necessary to specifically check for an in-source build to not add this directory because the conflict no long exists between the system string.h header file (not used) and project string.h header file (removed).
[commit f4a35bbab6] [commit 266022803b]
The Q_OBJECT macro is added to any class definition that contains Qt's C++ extensions for defining signals and slots, which are class sections in additional to the normal private, public and protected sections. These are handled by Qt's Meta-Object Compiler (moc), which produces a special MOC source file from the header file. For mainwindow.h, the special source file produced is moc_mainwindow.cxx, which then gets compiled and linked into the program.
In the CMake build file, this is handled by the qt4_wrap_cpp command that is added as part of the Qt4 CMake module. It is given a list of MOC source files and produces a list of MOC output source files. This output list is then specified as a dependency to the output executable. When a header file is included in the MOC sources list, it does not also need to be specified in the list of [normal] header files.
Qt form files are generated as an XML like language. This file needs to be converted into a class definition (within a header file) so that it can be used by the C++ code. These conversions are handled by Qt's User Interface Compiler (uic), which produces a special header file from the form file. For mainwindow.ui, the special header file produced is ui_mainwindow.h, which contains the Ui_MainWindow class. This source file is then included by the mainwinow.h header file.
In the CMake build file, this is handled by the qt4_wrap_ui command. It is given a list of form UI files and produces a list of user interface header files. This output list is then specified as a dependency to the output executive.
All of the generated files are placed in the CMake build directory, the same directory where the auto-generated header files (from the awk scripts) are placed. This directory (the project binary directory) is specified in the include_directories command, so that the C++ compiler can find all of these generated files. It is also no longer necessary to specifically check for an in-source build to not add this directory because the conflict no long exists between the system string.h header file (not used) and project string.h header file (removed).
[commit f4a35bbab6] [commit 266022803b]
Initial Main Window Implementation
The instance and running of the CommandLine class was moved from the main function to the constructor of MainWindow. A flag was added to the MainWindow class to indicate when the GUI is active (along with an access function). If the command line instance reports that the arguments have been processed, this flag is set to false. Otherwise (later), the GUI is setup and this flag is set to true.
In the main function, after the MainWindow is instanced (as a local variable), if the GUI is not active, a value of 0 (indicating no error) is returned. It is not necessary to have a single shot timer to force the event processing loop to exist immediately - simply returning before starting the event loop is sufficient.
The MainWindow class definition starts with the Q_OBJECT macro. Essentially this allows the use of signals and slots, which is a mechanism used by Qt to allow classes to communicate with each other. More on this later when these get implemented, but for now, the MainWindow class does not contain any of these, but will as the GUI is developed. Details about how these Qt GUI files are built with CMake in the next post.
In the main function, after the MainWindow is instanced (as a local variable), if the GUI is not active, a value of 0 (indicating no error) is returned. It is not necessary to have a single shot timer to force the event processing loop to exist immediately - simply returning before starting the event loop is sufficient.
The MainWindow class definition starts with the Q_OBJECT macro. Essentially this allows the use of signals and slots, which is a mechanism used by Qt to allow classes to communicate with each other. More on this later when these get implemented, but for now, the MainWindow class does not contain any of these, but will as the GUI is developed. Details about how these Qt GUI files are built with CMake in the next post.
Thursday, November 29, 2012
Qt Application – Main Window Class
The main window of a Qt Application contains the menu bar, any tool bars, optional dock widgets, a status line and a central widget (for example, contains the main document, which for this project will contain the BASIC program).
To create the new MainWindow class, the new file wizard in QtCreator was again used. This time the Qt type was selected under Files and Classes, and Qt Designer Form Class was selected on the right upper box, which will create both a C++ header and a source file for the new class along with Qt Designer form file. After clicking Choose..., the wizard asks for the form template type, where Main Window was selected. The defaults were selected for the remaining dialogs of the wizard.
The wizard sets up a simple form for main window containing a central widget, menu bar, main tool bar and a status bar. These can be seen in the Designer window in QtCreator (edit the mainwindow.ui file, by double clicking on it in QtCreator's project file list). For the moment, nothing will be down with this as it will remain inactive (temporarily). More about the initial implementation of this class in the next post.
To create the new MainWindow class, the new file wizard in QtCreator was again used. This time the Qt type was selected under Files and Classes, and Qt Designer Form Class was selected on the right upper box, which will create both a C++ header and a source file for the new class along with Qt Designer form file. After clicking Choose..., the wizard asks for the form template type, where Main Window was selected. The defaults were selected for the remaining dialogs of the wizard.
The wizard sets up a simple form for main window containing a central widget, menu bar, main tool bar and a status bar. These can be seen in the Designer window in QtCreator (edit the mainwindow.ui file, by double clicking on it in QtCreator's project file list). For the moment, nothing will be down with this as it will remain inactive (temporarily). More about the initial implementation of this class in the next post.
Monday, November 26, 2012
Command Line Class
To create the new CommandLine class, the new file wizard in QtCreator was used. The wizard is started by selecting New File or Project... on the File menu. The C++ type was selected under Files and Classes, and C++ Class was selected on the right upper box, which will create both a C++ header and a source file for the new class.
On the next dialog, the class name is entered and the wizard automatically creates the header and source file names along with the path, any of which can be changed. A Qt base class can also be selected, but wasn't for this class. The final dialog allow the new source files to be added to version control. If QMake was being used, the file would be added to the QMake build file, but for CMake, this has to be done manually.
This new class now handles the version option along with using the Tester class for the test options and running the tests if specified on the command line. The command line arguments are processed in the constructor, which sets a processed flag if the arguments result in using the command line only, or if an error occurs. There are only command lines at the moment, so this flag is always set. The intention is that the caller then checks this flag (via a constant access function) and if not set, the GUI will be started.
Besides the constructor, this class contains a private function for handling the version option and a function to get an output stream to the standard output device (which the output stream on the first call). The destructor deletes this output device if it was created. The class contains members for the program base name (no access function since it is currently only used internally), the processed flag, the output stream and a list of strings for the GPL statement.
Previously there was a function to output the GPL statement. As part of the constructor, a list of strings is created for this statement. The QT_TR_NOOP() macro is used (verses the tr() function) so that the strings will be found by the translation utilities. Only if the tr() function is used later on the strings will translations be used. This list is passed to the Tester class for output, but the tr() function is not used on the strings so they will not be translated in the test output (to make sure test results match the expected results).
The main function now creates a CommandLine instance passing the command line arguments to the constructor. If the processed flag is set (for now it will be), a single slot timer is connected to the application quit function to force the program to quit upon entered the event processing loop. The Tester class run function was modified to accept the GPL statement string list, which is output when appropriate.
[commit ea8e56dd68]
On the next dialog, the class name is entered and the wizard automatically creates the header and source file names along with the path, any of which can be changed. A Qt base class can also be selected, but wasn't for this class. The final dialog allow the new source files to be added to version control. If QMake was being used, the file would be added to the QMake build file, but for CMake, this has to be done manually.
This new class now handles the version option along with using the Tester class for the test options and running the tests if specified on the command line. The command line arguments are processed in the constructor, which sets a processed flag if the arguments result in using the command line only, or if an error occurs. There are only command lines at the moment, so this flag is always set. The intention is that the caller then checks this flag (via a constant access function) and if not set, the GUI will be started.
Besides the constructor, this class contains a private function for handling the version option and a function to get an output stream to the standard output device (which the output stream on the first call). The destructor deletes this output device if it was created. The class contains members for the program base name (no access function since it is currently only used internally), the processed flag, the output stream and a list of strings for the GPL statement.
Previously there was a function to output the GPL statement. As part of the constructor, a list of strings is created for this statement. The QT_TR_NOOP() macro is used (verses the tr() function) so that the strings will be found by the translation utilities. Only if the tr() function is used later on the strings will translations be used. This list is passed to the Tester class for output, but the tr() function is not used on the strings so they will not be translated in the test output (to make sure test results match the expected results).
The main function now creates a CommandLine instance passing the command line arguments to the constructor. If the processed flag is set (for now it will be), a single slot timer is connected to the application quit function to force the program to quit upon entered the event processing loop. The Tester class run function was modified to accept the GPL statement string list, which is output when appropriate.
[commit ea8e56dd68]
Sunday, November 25, 2012
String Comparisons
I realized that the various string comparisons in the code could be performed with the equality and inequality operators, which the QString class supports, instead of using the specific compare function, at least when case insensitive compares are not needed. With C character arrays, the string compare function was needed, but that is not the case with the higher level QString class.
[commit 11ae68634b]
[commit 11ae68634b]
Saturday, November 24, 2012
Tester Class – Single Option
As the design of the command line class was being developed, I realized that the Tester class should not be looping through all of the command line arguments. This lead to the problem mentioned at the end of the last post when other options are specified. The current version and test options are mutually exclusive - only one should be specified.
The version option was already checking to be make it is the only option specified. The Tester class was modified to also make sure only one of the test options are specified - there is no reason to loop through the command line arguments since the number of arguments must match the form used (either one of two arguments). This greatly simplified the Tester code.
All the access read only Tester functions were made constant (previously missed). A new access function was also added to return a list of valid test options, which is used by the caller to construct the usage message.
[commit 710414e4ba]
The version option was already checking to be make it is the only option specified. The Tester class was modified to also make sure only one of the test options are specified - there is no reason to loop through the command line arguments since the number of arguments must match the form used (either one of two arguments). This greatly simplified the Tester code.
All the access read only Tester functions were made constant (previously missed). A new access function was also added to return a list of valid test options, which is used by the caller to construct the usage message.
[commit 710414e4ba]
Subscribe to:
Posts (Atom)
