We've built the user interface through Qt Designer and connected those slots that provided sufficient default functionality. The last steps are to code the slots that require customization and then to create main.cpp so that we can compile and build our application.
When the user starts the richedit application we want the focus to be in the textEdit widget so we'll add one line of code to the init() function to achieve this. (All the code snippets are from eg/richedit/richedit.cpp which is generated by uic from richedit.ui.)
textEdit->setFocus(); |
The code for these tasks is straightforward. When the user clicks File|New we check to see if there are unsaved changes in the existing text and give them the opportunity to save, continue without saving or cancel the operation. When the user opts to open an existing file or exit the application we perform the same check and offer them the same choices.
void EditorForm::fileNew() { if ( saveAndContinue( "New" ) ) textEdit->clear(); } |
void EditorForm::fileOpen() { if ( saveAndContinue( "Open" ) ) { QString fn( QFileDialog::getOpenFileName( QString::null, "Rich Text Files (*.htm*)", this ) ); if ( !fn.isEmpty() ) { fileName = fn; QFile file( fileName ); if ( file.open( IO_ReadOnly ) ) { QTextStream ts( &file ); textEdit->setText( ts.read() ); } } } } |
void EditorForm::fileSave() { if ( fileName.isEmpty() ) { fileSaveAs(); } else { QFile f( fileName ); if ( f.open( IO_WriteOnly ) ) { QTextStream ts( &f ); ts << textEdit->text(); textEdit->setModified( FALSE ); } } } |
void EditorForm::fileSaveAs() { QString fn = QFileDialog::getSaveFileName( "", "Rich Text Files (*.htm*)", this ); if ( !fn.isEmpty() ) { fileName = fn; fileSave(); } } |
void EditorForm::fileExit() { if ( saveAndContinue( "Exit" ) ) qApp->exit(); } |
int EditorForm::saveAndContinue( const QString & action ) { int continueAction = 1; if ( textEdit->isModified() ) { switch( QMessageBox::information( this, "Rich Edit", "The document contains unsaved changes.\n" "Do you want to save the changes?", "&Save", "&Don't Save", "&Cancel " + action, 0, // Enter == button 0 2 ) ) { // Escape == button 2 case 0: // Save; continue fileSave(); break; case 1: // Do not save; continue break; case 2: // Cancel continueAction = 0; break; } } return continueAction; } |
void EditorForm::changeAlignment( QAction * align ) { if ( align == leftAlignAction ) textEdit->setAlignment( Qt::AlignLeft ); else if ( align == rightAlignAction ) textEdit->setAlignment( Qt::AlignRight ); else if ( align == centerAlignAction ) textEdit->setAlignment( Qt::AlignCenter ); } |
We've already connected the fontComboBox's activated() signal to the textEdit's setFamily() slot so we just have to populate the combo box with the font names when we call init().
void EditorForm::init() { textEdit->setFocus(); QFontDatabase fonts; fontComboBox->insertStringList( fonts.families() ); QString font = textEdit->family(); font = font.lower(); for ( int i = 0 ; i < fontComboBox->count(); i++ ) { if ( font == fontComboBox->text( i ) ) { fontComboBox->setCurrentItem( i ); break; } } } |
With all the connections and code in place we are now ready to make our application run. Click on the Source tab of the Object Hierarchy window and click on the Includes (in Implementation) item. We need to include the files that our source code depends on. Right click the Includes item and click New. Type in <qapplication.h> for fileExit()'s exit() call. In the same way add <qmessagebox.h> for saveAndContinue()'s message box, <qfiledialog.h> for the fileOpen() and fileSaveAs() functions, and <qfontdatabase.h> for the QFontDatabase class in init().
We referred to a member variable, fileName, in our source code so we must add it to the form. Click the Source tab, right click the Class Variables item, click New from the pop up menu, then enter 'QString fileName;'.
Create a main.cpp file in a plain text editor. Ours looks like this:
#include <qapplication.h> #include "richedit.h" int main( int argc, char *argv[] ) { QApplication app( argc, argv ); EditorForm richeditForm; app.setMainWidget( &richeditForm ); richeditForm.show(); return app.exec(); } |
In a plain text editor open the richedit.pro project file and add the line SOURCES += main.cpp to the end of the file. The file should look similar to this:
TEMPLATE = app CONFIG += qt warn_on release TARGET = richedit INTERFACES = richedit.ui DBFILE = richedit.db IMAGEFILE = images.cpp PROJECTNAME = richedit LANGUAGE = C++ {SOURCES+=images.cpp} SOURCES += main.cpp |
The richedit application demonstrates how easy it is to create a Qt application's main window with menus and dockable toolbars. A great deal of functionality was obtained by connecting the appropriate built-in signals and slots. The remaining functionality was achieved by connecting built-in signals to our own custom slots. We could continue developing the application, for example updating the fontComboBox, the font size spinbox and the actions with the font attributes as the user moves the cursor through their text. But our objective has been to demonstrate the creation of a main window with actions, menus and toolbars so we must stop at this point and leave further development and experimentation to you.