Viadeo Twitter Google Bookmarks ! Facebook Digg del.icio.us MySpace Yahoo MyWeb Blinklist Netvouz Reddit Simpy StumbleUpon Bookmarks Windows Live Favorites 
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Classes principales  ·  Annotées  ·  Classes groupées  ·  Fonctions  · 

Replacing the View Widget

[ Previous: Refactoring Existing Code ] [ Home ] [ Next: Replacing the Print Dialog ]

We are ready to start replacing the View widget. However, our example program uses the XmNotebook widget class. Qt does not provide a direct equivalent of this class, so we are faced with three possibilities, each with several advantages and disadvantages.

  1. We can continue the conversion using existing Qt widgets.

    • Advantages - The widgets provided by Qt are well designed and tested, allowing us to quickly redesign the user interface.

    • Disadvantages - Most, if not all, of the existing data structures and code will need to be modified or rewritten. New code must be written in a way that maintains compatibility with previous versions of our application.

  2. We can write a new QWidget subclass that is identical to the XmNotebook widget class.

    • Advantages - The existing data structures will not change, allowing compatibility with previous and future versions.

    • Disadvantages - The new widget will need to be written and regression tested. Existing code in our application will need to be changed in order to deal with the new widget's API.

  3. We can leave the XmNotebook widget untouched.

    • Advantages - The existing data structures and code remain unchanged, allowing us to continue development on other projects, new features, etc.

    • Disadvantages - This is the simplest solution, but the application will still be dependent upon X11; we will not be able to deploy our application on all platforms supported by Qt.

We will use the first approach to complete the migration of the example project used in this walkthrough, using QTextEdit, QLabel and QSpinBox to provide a similar look. The only difference is that we will not have tabs.

We use Qt Designer to add the QTextEdit, QLabel and QSpinBox widgets to the Main Window widget.

Data Structure Modifications

The Page struct contains majorPB and minorPB members which need to be removed.  These members correspond to the tabs displayed in the existing version. The new version will not have any tabs, so we remove them.

    struct Page {
        Page()
            : page( 0 ), majorTab( 0 ), minorTab( 0 ),
              label( 0 ), lasttoppos( 0 ), lastcursorpos( 0 )
        {
        }

        ~Page()
        {
            delete [] page;
            delete [] majorTab;
            delete [] minorTab;
            delete [] label;
        }

        char *page;
        char *majorTab;
        char *minorTab;
        char *label;
        int lasttoppos;
        int lastcursorpos;
    };

Code Modifications

Most of the existing functions in our application need to be modified to work with the new View widget. The MainWindow class has five new functions that correspond to existing functions.

Existing Function New Function
void SetPage( int ) void MainWindow::setPage( int )
void PageChange( ... ) void MainWnidow::pageChange( int )
void TextChanged( ... ) void MainWnidow::textChanged()
void ReadDB( char * ) void MainWindow::readDB( char * )
void SaveDB( char * ) void MainWindow::saveDB( char * )

The SetPage() function implementation is moved to the MainWindow::setPage() function in mainwindow.ui.h. We remove the SetPage() function declaration and implementation from page.h and actions.cpp, respectively. In order to make MainWindow::setPage() work correctly, we need to modify the code to use the new widgets in our Main Window widget.

    void MainWindow::setPage( int pageNumber )
    {
        currentPage = pageNumber;

First, we set the current value of the spinbox to the current page number.

        if (pageNumber <= maxpages)
            spinbox->setValue( pageNumber + 1 );

Next, we set the current text and cursor position of the textedit to the contents of the current page.

        if ( pages[pageNumber] ) {
            textedit->setText( QString::fromLocal8Bit( pages[pageNumber]->page ) );
            textedit->setCursorPosition( pages[pageNumber]->lasttoppos,
                                         pages[pageNumber]->lastcursorpos );

            QString labeltext;

If the current page has a custom label, we set it as the current text of the textlabel; otherwise we set the textlabel contents to "Page X" (where X is the current page number).

            if ( pages[pageNumber]->label ) {
                labeltext =
                    QString::fromLocal8Bit( pages[pageNumber]->label );
            } else {
                labeltext =
                    QString::fromLocal8Bit("Page %1" ). arg( pageNumber + 1 );
            }

If the current page has major and/or minor tab text, we append these to the labeltext. This ensures that all information entered by the user remains visible.

            if ( pages[pageNumber]->majorTab ) {
                labeltext +=
                    QString::fromLocal8Bit( " - " ) +
                    QString::fromLocal8Bit( pages[pageNumber]->majorTab );
            }

            if ( pages[pageNumber]->minorTab ) {
                labeltext +=
                    QString::fromLocal8Bit( " - " ) +
                    QString::fromLocal8Bit( pages[pageNumber]->minorTab );
            }

            textlabel->setText( labeltext );

We should continue to handle the possibility that the current page does not exist. In this case, we clear the contents of the textedit widget and set the textlabel contents to the current page number (with an indication that the page is invalid).

        } else {
            textedit->clear();

            QString labeltext =
                QString::fromLocal8Bit("Page %1 (Invalid Page)").arg( pageNumber + 1 );
            textlabel->setText( labeltext );
        }
    }

The PageChange() function is moved from todo.cpp to the MainWindow::pageChange() function in mainwindow.ui.h. As with the MainWindow::setPae() function, we need to modify the code to use the new widgets in our Main Window widget.

Note: QTextEdit::text() returns a QString, which needs to be converted into a normal char* array. To do this we create a copy of the string in the local encoding. We need to make the copy using qstrdup() because the data contained in the QCString returned by QString::local8Bit() is deallocated when the QCString is destroyed.

    void MainWindow::pageChange( int pageNumber )
    {
        if ( modified && pages[currentPage] ) {
            delete pages[currentPage]->page;
            pages[currentPage]->page = qstrdup( textedit->text().local8Bit() );

            textedit->getCursorPosition( &pages[currentPage]->lasttoppos,
                                         &pages[currentPage]->lastcursorpos );
        }

        setPage( pageNumber - 1 );
    }

The TextChanged() function does nothing more than set the modified variable to 1. Our new MainWindow::textChanged() function does exactly the same.

    void MainWindow::textChanged()
    {
        modified = 1;
    }

Since both the MainWindow::pageChange() and MainWindow::textChanged() functions access the modified global variable, we add a forward declaration at the top of mainwindow.ui.h.

The ReadDB() and \s SaveDB() implementations in io.cpp are renamed to MainWindow::readDB() and MainWindow::saveDB(), respectively. We need to modify the code in order to make the code work properly.

First, We add #include statements for the MainWindow, QSpinBox and QTextEdit classes.

    #include "mainwindow.h"
    #include "page.h"
    #include <qmessagebox.h>
    #include <qspinbox.h>
    #include <qtextedit.h>

The new MainWindow::readDB() and MainWindow::saveDB() functions will not use any Xt/Motif functions, so we remove the Xt/Motif #include statements and the global variables notebook and textw. These functions remain largely unchanged, maintaining compatibility with previous versions. Also, the ReadDB() and SaveDB() functions have been converted into MainWindow member functions, so we can pass this as the parent argument to the QMessageBox functions.

        QMessageBox::warning( this, "IO Error", message.arg(filename) );

After reading the file in the MainWindow::readDB() function, we set the current and maximum values of the spinbox to the appropriate values.

      maxpages = number;
      spinbox->setMaxValue( maxpages + 1 );
      spinbox->setValue( 1 );

      if (input) fclose(input);

In the MainWindow::saveDB() function, we need to store the text currently displayed, so we use QTextEdit::text() instead of XmTextGetString(). Note: QTextEdit::text() returns a QString, which needs to be converted into a normal char* array. To do this we create a copy of the string in the local encoding. We need to make the copy using qstrdup() because the data contained in the QCString returned by QString::local8Bit() is deallocated when the QCString is destroyed.

      /* Make sure to grab current page */
      if (modified) {
        delete pages[currentPage] -> page;
        pages[currentPage] -> page = qstrdup( textedit->text().local8Bit() );
      }

Due to the removal of the majorPB and minorPB members from the Page struct, the FixPages() function in actions.cpp is no longer needed. We remove the implementation and forward declaration of FixPages() from actions.cpp and page.h, respectively. Calls to FixPages() are removed from the MainWindow::selNewPage() and MainWindow::selDeletePage(), both of which are in mainwindow.ui.h.

We move AdjustPages() to mainwindow.ui.h and make it static, since it is only used in this file. We remove the forward declaration from page.h as well.

After our modifications, the actions.cpp file is empty. We remove it from our project file and regenerate our Makefile.

Now that we have implemented our new View widget, we need to remove the old Motif based view widget from todo.cpp.

Since we will not be using any Motif widgets, we remove all Motif #include statements, including qmotifwidget.h.

    #include "mainwindow.h"
    #include "page.h"
    #include <qapplication.h>
    #include <qmotif.h>

    #include <pwd.h>
    #include <unistd.h>
    #include <stdlib.h>

We also remove the forward declarations of the ReadDB() function and the notebook, textw and labelw global variables.

    Page *pages[MAXPAGES];
    int currentPage = 1;
    int maxpages = 0;

    Options options;

    int modified = 0;

Next, we remove the center widget, which uses QMotifWidget. The Main Window widget and View widget are contained entirely in our MainWindow class, so no extra initialization is needed after creating the mainwindow widget.

    int main( int argc, char **argv )
    {
      int i;
      char temppath[256];

      if (argc == 2 && strcmp(argv[1], "-help") == 0) {
        printf("Usage: todo [-todoFile pathname]\n");
        return(0);
      }

      QMotif integrator( APP_CLASS );
      QApplication app( argc, argv );
      MainWindow mainwindow;
      app.setMainWidget( &mainwindow );

Since the ReadDB() and SetPage() functions have been changed into MainWindow member functions, we need to call them using our mainwindow instance.

      mainwindow.readDB(options.todoFile);
      mainwindow.setPage(0);

      mainwindow.show();

      return app.exec();
    }

The View widget has now been replaced. After building our project, we confirm that the application works correctly.

[ Previous: Refactoring Existing Code ] [ Home ] [ Next: Replacing the Print Dialog ]

Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt 3.2
Copyright © 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur ? Un bug ? Une redirection cassée ? Ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
 
 
 
 
Partenaires

Hébergement Web