Coding between Mouse and Keyboard, Part II
In Part I of this series [LJ, September 2002] we created the GUI of a tiny text editor using Qt Designer. Now, we add missing functionality and translate the application into other languages by using our favourite editor along with make and the g++ C++ compiler, and use Qt Linguist as an attractive working environment during translation.
We use the new qmake utility to write the Makefile for our Qt application; qmake outdates tmake, a Perl tool widely used with older Qt versions.
Our editor GUI already closes windows and the entire application, but we still lack a user dialog that asks whether the old data should be saved or discarded or whether the user wants to stay with the old file. The New, Save and Save As actions do nothing right now, but everything else was completed. The GUI already supports copy, cut and paste, undo and redo. It can switch font characteristics to italic, bold, underlined and any combination of the three. These QTextEdit actions already can be tested in the Qt Designer preview. The About entry in the Help menu will be fully functional as soon as we compile the GUI into a C++ program.
We could write the remaining functions using Qt Designer's built-in code editor. As there are no means to compile the project within the Designer, however, using one's favourite text editor is faster.
Now that we have the user interface ready in a ui file for the interface description, and a ui.h file containing the code already written, it's time to implement the remaining functionality. First we have to convert the XML to C++ with the User Interface Compiler, uic, but using qmake we don't need to worry about this detail. Let's feed it the project file generated by the Designer:
qmake -o Makefile lj-article.pro
A Makefile is created with a subdirectory named .ui that is supposed to store the C++ code generated from the ljeditor.ui and ljeditor.ui.h files. If this fails and you are asked to set the QMAKEPATH, set this variable to the mkspecs subdirectory of your Qt installation, which describes your operating system and compiler. For example:
QMAKEPATH=$QTDIR/mkspecs/linux-g++ export QMAKEPATHDepending on where you have installed Qt, make sure that the search path contains the $QTDIR/bin directory of the used Qt version.
To generate the C++ files simply type:
make .ui/ljeditor.h make .ui/ljeditor.cpp
If problems arise, check the environment variables QTDIR, PATH and LD_LIBRARY_PATH. The first one should point to the directory parenting the Qt 3.0 subdirectories lib and include. The directories where uic, qmake and designer live should be included in the path, and $QTDIR/lib should be added to the linker path.
Editing the two generated files means the changes are lost when the ui file is moved to the Designer and a new conversion round becomes necessary. So, we derive a subclass from ljeditor and add our changes to it instead of to ljeditor.
uic offers the command-line switches -subdecl classname and -subimpl classname to build the appropriate code skeletons. With
uic -o editor.h -subdecl Editor .ui/ljeditor.h \ ljeditor.ui
we obtain editor.h, the header file for the new Editor subclass. On the other hand (mind the argument header file), the following line creates the implementation skeleton in editor.cpp:
uic -o editor.cpp -subimpl Editor editor.h \ ljeditor.uiThese new files need to be added to the project file by adding two lines:
HEADERS += editor.h SOURCES += editor.cppto lj-article.pro. Or you could start Qt Designer, open the project file and add them via Project®Add File. Remember to set the File type to C++ Files, otherwise the file dialog won't find them). If you like the text editor included in the Designer, you even might edit them there.
The subclass code generated by uic always includes skeletons for all functions present in the parent class. Thus, it's a good idea to delete the declarations and function skeletons of all functions that you don't plan to re-implement in the subclass. Remove the lines:
void fileExit(); void helpAbout(); void fileClose();
from editor.h and the relevant code skeletons from editor.cpp, which look like:
void Editor::fileExit()
{
qWarning( "Editor::fileExit() "
"not yet implemented!" );
}
For a complete program we still need a main() function. We may
write it by hand, but Qt Designer can help you a little. Choose
File®New®C++ Main-File (main.cpp) from the menu and the
subsequent dialog.
The dialog shown in Figure 1 asks us to name the main file (we choose ljedit.cpp) and the main widget. Designer does not provide the Editor subclass here; thus we don't really have a choice and choose ljeditor.

Figure 1. Configuring the main File
Choosing this name means we have to correct the generated code. Instead of ljeditor.h, we include editor.h, and instead of creating a new object of the ljeditor class, we need an Editor one. Now our ljedit.cpp should look like this:
#include <qapplication.h>
#include "editor.h"
int main( int argc, char ** argv )
{
QApplication a( argc, argv );
Editor *w = new Editor;
w->show();
a.connect( &a, SIGNAL( lastWindowClosed() ),
&a, SLOT( quit() ) );
return a.exec();
}
As in every usual Qt main(), we create a QApplication object, hand it possible command-line arguments (argv) and create the Editor widget w. Then we show it to the world and enter the application loop with a.exec().
You may notice that a a.setMainWidget( w ); line is missing that defines the main widget of the application (we'll explain this later). However, without a main widget, the application will not quit when the last window is closed. So, we have to connect the application object's signal, lastWindowClosed(), to its quit() slot.
make and a subsequent ./lj-article in the project directory should result in a running, yet not fully functional text editor. If you wish to call the binary by something other than the project file's base name, add the line TARGET = ljedit to lj-article.pro.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
- RSS Feeds
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- Dynamic DNS—an Object Lesson in Problem Solving
- New Products
- Validate an E-Mail Address with PHP, the Right Way
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Download the Free Red Hat White Paper "Using an Open Source Framework to Catch the Bad Guy"
- Tech Tip: Really Simple HTTP Server with Python
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




1 hour 10 min ago
6 hours 23 min ago
9 hours 34 min ago
11 hours 50 min ago
12 hours 18 min ago
13 hours 16 min ago
14 hours 45 min ago
15 hours 54 min ago
16 hours 40 min ago
23 hours 16 min ago