Coding between Mouse and Keyboard, Part I

This article shows you how to create the GUI of a tiny text editor without being a C++ guru. In Part II, we'll add missing functionality and translate the program into languages other than English.
Adding Some Code

Closing a widget in Qt is easy: every Qt widget inherits a close() function from the mother of all Qt widgets, QWidget. This is not really much code, so it would be nice if we could fill the fileClose() slot with this one line.

A right-mouse click on the ljeditor form opens a context menu. The choice of its Source... entry does the trick. A code editor window appears and allows us to fill in the one-liner (see Figure 8):

void ljeditor::fileClose()

Figure 8. Simple code lines are easily added to the slot skeleton.

So why not fill the fileExit() slot as well? To quit the entire application, the application object's closeAllWindows() function is called:

void ljeditor::fileExit()

As the Designer usually does not deal with QApplication objects itself, qapplication.h (which provides the qApp proxy for the real application object) is not included by default, and the code generated from the ui description would not compile.

Fortunately, the Object Explorer allows us to include additional header files. By default it shows the Widgets tab (see Figure 4, bottom left), but we need the Source tab right now. Right-clicking the empty Includes (in Implementation) folder allows us to add a header file (New). Don't forget the <> brackets around a global include like <qapplication.h> (Figure 9).

Figure 9. The Object Explorer allows one to include additional header files.

Another slot we can fill with life without being afraid of getting too many compilation errors is helpAbout(). It is called when the user opens the About... entry in ljeditor's Help menu and simply pops up a message box with the caption About ljedit and some information about the program. By surrounding all text strings with tr() we make sure that the program can be localized painlessly, a task we will fulfill in Part II. For example:

void ljeditor::helpAbout()
    QMessageBox::about( this, tr( "About ljedit" ),
        tr( "A tiny text editor.\n"
        "(C) 2002 Patricia Jung for Linux Journal\n"
        "Using Qt 3.0.4 and Qt Designer." ) );

To be able to use QMessageBox::about(), we have to include <qmessagebox.h> the same way we did with <qapplication.h>. We add the remaining functionality in a subclass next time. Thus, all we have left to do with the Designer is clean up the new GUI.

Important Cosmetics

Before we leave the Designer for good, we check that none of the assigned keyboard shortcuts has been used twice. This is done by choosing Check Accelerators from the Edit menu.

Additionally, we clean up all the ljeditor slots that we weren't going to implement anyway or that we used TextEdit slots for instead. By choosing Slots from the Edit menu (one way to do it), we open the dialog that allows us to mark editUndo() and remove it with a mouse click on Delete Slots (Figure 7). The same fate applies to editRedo(), editCut(), editCopy(), editPaste(), editFind(), helpIndex(), helpContents() and filePrint().

Furthermore, we check the GUI preview for separators that don't fit. As we decided against using the editFindAction, a single separator can be found at the end of ljeditor's Edit menu: once upon a time there was a Find entry below. To erase the separator, right-click on it in the form and choose Delete Item. The same applies to one of the two separators above the Exit entry in the file menu.

All GUI elements are in their place—time to let Qt adjust the widget proportions. Once again, we choose the entire form and select Lay Out Vertically from Layout in the main menu. If a user adjusts the application window size now, the TextEdit widget will follow. If we wish to place widget elements differently onto the form, we need to break the layout first.

Last but not least, we want this GUI to be stamped as ours. To do this we fill in the Author name and a description in the dialog raised by choosing Form Settings from the Edit menu (see Figure 10). Here it is possible to decide whether we want to store the icons in a subdirectory of our project directory or whether we include them directly in the user-interface description.

Figure 10. Let the world know who designed this GUI.

A final selection of Save all from the File menu and an XML file with the user-interface description (best named after the relevant class, e.g., ljeditor.ui) along with ljeditor.ui.h, the file storing the code we typed into the code editor, becomes part of the project.

Patricia Jung ( has a background as a system administrator, technical writer and editor, and as such is happy to have the privilege of dealing with Linux/UNIX exclusively.


White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState