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

[Previous: Replacing the View Widget] [Home] [Next: Continuing Development]

# Replacing the Print Dialog

The Print dialog is the last component in our application that uses Motif. The current `Print()` function does nothing more than write the plain text to a temporary file, and then executes 'lpr' to send the text to the printer. Since we will use QPrinter, we do not this function any more, so we remove it. The current `MainWindow::filePrint()` implementation is removed as well. We will write a new `MainWindow::filePrint()` implementation in `mainwindow.ui.h`.

Note: The steps involved in using the QPrinter class are beyond the scope of this walkthrough and will not be discussed here. The QPrinter Class Reference, QSimpleRichText Class Reference and the Simple Application Walkthrough contain information on the use of QPrinter.

For completeness, the code to initialize a QPrinter object is included below.

        void MainWindow::filePrint()
        {
            QPrinter printer( QPrinter::HighResolution );
            printer.setFullPage(true);
            if ( ! printer.setup( this ) ) return;

            QPainter p( &printer );
            if ( ! p.isActive() || ! p.device() ) return;

## Using Rich Text for Printing

Qt provides rich text using a subset of HTML. The QSimpleRichText class makes rich-text printing simple. All we need to do is create a string with the proper format tags inserted at the appropriate places. For our example, we will keep the printing output similar to previous versions.

First, we create the format tags that we will use.

            const QString prelabel  = QString::fromLatin1( "<b>Subject: " );
            const QString postlabel = QString::fromLatin1( "</b>" );
            const QString prepage   = QString::fromLatin1( "<p>" );
            const QString postpage  = QString::fromLatin1( "</p>" );
            const QString pagebreak = QString::fromLatin1( "<hr>" );

Next we just loop over all pages, appending the page label, contents and formatting characters to a `printtext` variable (which is a QString).

            QString printtext;
            for( int i = 0 ; i <= maxpages ; i++ ) {
                if ( pages[i]->label ) {
                    printtext += prelabel;
                    printtext += QString::fromLocal8Bit( pages[i]->label );
                    printtext += postlabel;
                }

                printtext += prepage;
                printtext += QString::fromLocal8Bit( pages[i]->page );
                printtext += postpage;

                if ( i != maxpages )
                    printtext += pagebreak;

The rest of the `MainWindow::filePrint()` function is the actual printing code. Here we simply create a QSimpleRichText object using the string we created above, and draw this string on the QPrinter object using QPainter.

            QPaintDeviceMetrics metrics( p.device() );
            int dpiy = metrics.logicalDpiY();
            int margin = (int) ( (2/2.54)*dpiy ); // 2 cm margins
            QRect body( margin, margin, metrics.width() - 2*margin,
                        metrics.height() - 2*margin );

            QFont font( font() );
            font.setPointSize( 10 ); // we define 10pt to be a nice base size for printing

            QSimpleRichText richText( printtext, font, QString::null, 0, 0, body.height() );
            richText.setWidth( &p, body.width() );
            QRect view( body );
            int page = 1;
            do {
                qApp->eventLoop()->processEvents( QEventLoop::ExcludeUserInput );

                richText.draw( &p, body.left(), body.top(), view, colorGroup() );
                view.moveBy( 0, body.height() );
                p.translate( 0 , -body.height() );
                p.setFont( font );

                QString pageString = QString::number( page );
                p.drawText( view.right() - p.fontMetrics().width( pageString ),
                            view.bottom() + p.fontMetrics().ascent() + 5, pageString );
                if ( view.top()  >= richText.height() )
                    break;
                printer.newPage();
                page++;
            } while (true);

            qApp->restoreOverrideCursor();

## Removing the Dependency on Xt/Motif

Our application no longer uses any Xt or Motif widgets. We can now finish removing the dependencies on Xt and Motif.

First, we cleanup the `#include` statements in `mainwindow.ui.h`.

        #include "pageeditdialog.h"
        #include "page.h"

        #include <qapplication.h>
        #include <qeventloop.h>
        #include <qfiledialog.h>
        #include <qlineedit.h>
        #include <qmessagebox.h>
        #include <qpainter.h>
        #include <qpaintdevicemetrics.h>
        #include <qprinter.h>
        #include <qsimplerichtext.h>
        #include <qstatusbar.h>

        #include <unistd.h>

The `MainWindow::fileNew()` function uses the `Boolean` and `False` keywords from the Xt library. C++ has these built into the language, so we use `bool` and `false` instead.

The last modification needed to completely remove Xt and Motif from our application is to stop using the QMotif class. We remove the qmotif.h `#include` statement from `todo.cpp`, and remove the instantiation from the `main()` function.

After doing this, we can remove the `-lXm` and `-lqmotif` from the `LIBS` variable in our project file. Our project file also contains source and headers for the the old custom Motif widgets previously used in our application. We remove these as well.

After regenerating the `Makefile` and building our project, we confirm that the application works correctly.

[Previous: Replacing the View Widget] [Home] [Next: Continuing Development]