Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions

Refactoring Existing Code

[ Previous: Using Qt Main Window Classes ] [ Home ] [ Next: Replacing the View Widget ]

In the author's view, the existing code is slightly disorganized. Even though the code does work, some cleanups and reorganization can only help with readability and maintainability. The steps described below are not necessary during the migration process but are included for completeness.

Migrating Data Structures to C++

The Page data structure is an opaque data type. The real data structure is called PageRec; Page defined to be a pointer to a PageRec. In addition, we have the AllocPage() function that allocates and initializes memory for a PageRec struct.

With C++, we can do this in the constructor. We can also write a destructor which automatically frees all resources in the PageRec, instead of having to do it in several different places.

The PageRec struct declaration is removed from page.h. We declare a Page struct with the same data members as PageRec, a constructor and a destructor.

The existing pages, currentPage and maxpages global variables are removed from the source files. We replace them with extern declarations in page.h.

The global variable instantiations are placed in todo.cpp.

Each source file contains function declarations that deal with the global Page related variables. We remove these declarations from the source files and declare them once in the page.h header file.

Now that Page has a constructor, we remove the AllocPage() function. It is no longer needed. The calls to AllocPage() are replaced with 'new Page()' in the NewPage(), DeletePage() and ReadDB() functions. We also replace the code to deallocate pages with delete pages[X], where X is the appropriate index value. This is done in the ReadDB and DeletePage() functions.

Code that accesses the global pages variable does not need to be modified since the data members of the Page struct did not change. The existing code will continue to work.

The OptionsRec struct declared in page.h is also updated, following the same pattern as the Page struct above.

The global variable instantiation is also placed in todo.cpp.

Code that accesses the global options variable does not need to be modified since the data members of the Options struct did not change. The existing code will continue to work.

Using new and delete

The destructors of the Page and Options structs use delete instead of XtFree() to deallocate all char* members. This is a necessary change since we are migrating away from Xt/Motif. We need to fix existing code that modifies the Page struct members to use new and delete ( instead of XtMalloc(), XtNewString() and XtFree() ).

The PageChange() function in todo.cpp simply saves the contents and cursor position of current page before calling SetPage(). We use new and delete when modifying members of the Page struct.

When storing the context of the XmText widget, we use qstrdup() to make a copy of the string returned by the XmTextGetString() function.

The ReadDB() function in io.cpp needs similar changes. We replace all use of XtMalloc() and XtNewString() with new and qstrdup(), respectively.

This needs to be done just after opening the file.

... when starting a new page ...


... and when reading in the label and tab texts/


The ReadDB() function uses XtRealloc() to expand the data storage buffer. Unfortunately, C++ does not provide a way to reallocate an existing block of data, so we have to do this ourselves.

There is also one occurence in ReadDB() where we call XtMalloc() with an argument of 2. This was done when a file could not be read. Creating an empty string is not necessary, so we remove this code instead of using new.

The SaveDB() function in io.cpp also needs these changes. We change one occurence of XtFree() to delete.

Finally, We need to replace two occurences of XtNewString() in the main() function in todo.cpp.

Moving Existing Code

The rest of the refactoring process involves moving existing code into new places. Currently, each function in the mainwindow.ui.h file simply calls the old callback handlers present in the other files. Instead of calling the old callback functions, the implementations are moved accordingly.

Function Original File Moved to Function
New() todo.cpp MainWindow::fileNew()
Open() todo.cpp MainWindow::fileOpen()
SaveIt() actions.cpp MainWindow::fileSave()
Save() todo.cpp MainWindow::fileSaveAs()
ShowPrintDialog() todo.cpp MainWindow::filePrint()
EditPage() actions.cpp MainWindow::selProperties()
NewPage() actions.cpp MainWindow::selNewPage()
DeletePage() actions.cpp MainWindow::selDeletePage()

The Print() callback function is still used by the Print dialog, so we move it into mainwindow.ui.h and make it static.

Previously, the Open(), Save(), EditPage() and DeletePage() functions created dialogs with client_data as the parent argument. Since we have moved the code directly into the Main Window implementation, we create these dialogs with this as the parent argument.

The PageChange() callback function is moved from actions.cpp to todo.cpp and made static since it is not used anywhere else.

Earlier modifications to actions.cpp caused the Trim() function to become redundant, so we remove it.

The MIN() and MAX() macros in todo.cpp are redundant. Qt provides the QMIN() and QMAX() macros which we will use.

Earlier modifications caused the fallback_resources array to become redundant, so we remove it.

In the near future, our program will not use Motif any more, and we will no longer need to use QMotif. To prepare for this, we remove the resources and optionDesc arrays and create the QMotif instance with just the APP_CLASS argument.

The #include statements in the source files are mostly incorrect due to the refactoring changes. Many of the #include statements are no longer needed. The #include statements from each file are listed below, instead of describing which includes are removed and added to each file.

Includes for actions.cpp:

Includes for io.cpp:

Includes for todo.cpp:

Includes for mainwindow.ui.h:

[ Previous: Using Qt Main Window Classes ] [ Home ] [ Next: Replacing the View Widget ]

Copyright © 2007 TrolltechTrademarks
Qt 3.3.8