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  · 

Using Qt Standard Dialogs

[ Previous: Preparing to Migrate the User Interface ] [ Home ] [ Next: Using Custom QDialogs ]

We start by using two of the Qt Standard Dialogs: QFileDialog and QMessageBox. Both of these classes provide useful static convenience functions.

QFileDialog::getOpenFileName() replacement for the Open dialog
QFileDialog::getSaveFileName() replacement for the Save As dialog
QMessageBox::information() replacement for Page Delete dialog
QMessageBox::warning() replacement for IO Error dialog.

Each of these functions takes a QWidget *parent argument. If we pass zero as the parent argument, then we will have dialogs that are centered on the screen, instead of being centered over our main window. We can have QMotifWidget create our XmMainWindow, and we can then use this class as the parent for both Motif dialogs and Qt dialogs.

We need to include the appropriate headers for QMotifWidget and QFileDialog in todo.cpp.

    // Qt includes
    #include <qapplication.h>
    #include <qfiledialog.h>
    #include <qmotif.h>
    #include <qmotifwidget.h>

Next, we make a few modifications to how the application is initialized. We could initialize Xt/Motif and create the XtAppContext ourselves, but QMotif can do this for us. We also let QApplication open the connection to the X server. Next, we create a QMotifWidget, passing xmMainWindowWidgetClass as the widgetclass argument. We can now use the QMotifWidget::motifWidget() function to access the Motif widget. The shell widget is created automatically by QMotifWidget. We use XtParent() to access it. The top-level window is now a QMotifWidget, which means we can use it as the parent for the Qt Standard Dialogs.

      QMotif integrator( APP_CLASS, NULL,
                         optionDesc, XtNumber(optionDesc) );
      QApplication app( argc, argv );
      QMotifWidget toplevel( 0, xmMainWindowWidgetClass,
                             NULL, 0, "mainw" );
      app.setMainWidget( &toplevel );

      mainw         = toplevel.motifWidget();
      shell         = XtParent( mainw );
      XtGetApplicationResources(shell, (XtPointer) &options,
                                resources, XtNumber(resources),
                                (Arg *) NULL, 0);

      XtManageChild(mainw);

Replacing the Open and Save As Dialogs

First, we completely remove all use of the existing Motif file selection dialog. We remove the Xm/FileSB.h include, the global file_dialog variable, and the code to create the dialog. We also remove the PresentFDialog() callback function. None of this code is needed to use QFileDialog.

After removing the PresentFDialog() callback function, we need to make Open and Save As popup-menu callbacks call the Open() and Save() functions.

First we must change the declaration of these two functions.

        // void Open(Widget, char*, XmFileSelectionBoxCallbackStruct *);
        void Open(Widget, XtPointer, XmPushButtonCallbackStruct *);
        // void Save(Widget, char*, XmFileSelectionBoxCallbackStruct *);
        void Save(Widget, XtPointer, XmPushButtonCallbackStruct *);

We also change the arguments to the callbacks. We pass the top-level QMotifWidget as the client_data to these functions, since we will be using it as the parent for the QFileDialog.

      // XtAddCallback(file_menu[FILE_OPEN], XmNactivateCallback,
      //               (XtCallbackProc) PresentFDialog, (XtPointer) Open);
      XtAddCallback(file_menu[FILE_OPEN], XmNactivateCallback,
                    (XtCallbackProc) Open, (XtPointer) &toplevel);

    ...

      // XtAddCallback(file_menu[FILE_SAVE_AS], XmNactivateCallback,
      //               (XtCallbackProc) PresentFDialog, (XtPointer) Save);
      XtAddCallback(file_menu[FILE_SAVE_AS], XmNactivateCallback,
                    (XtCallbackProc) Save, (XtPointer) &toplevel);

Next, we modify the Save() function to use QFileDialog::getSaveFileName().

    void
    Save(Widget /*unused*/, XtPointer client_data,
         XmPushButtonCallbackStruct */*unused*/)
    {
      QWidget *toplevel = (QWidget *) client_data;
      QString filename =
          QFileDialog::getSaveFileName( QString::null,
                                        QString::null,
                                        toplevel );

      if ( ! filename.isEmpty() ) {
        char *str = qstrdup( filename.local8Bit() );
        SaveDB(str);

... and the Open() function to use QFileDialog::getOpenFileName().

    void
    Open(Widget /*unused*/, XtPointer client_data,
         XmPushButtonCallbackStruct */*unused*/)
    {
      QWidget *toplevel = (QWidget *) client_data;
      QString filename =
          QFileDialog::getOpenFileName( QString::null,
                                        QString::null,
                                        toplevel );

      if ( ! filename.isEmpty() ) {
        char *str = qstrdup( filename.local8Bit() );
        ReadDB(str);

After we build the project, the application runs and operates as expected. The difference is that the Open and Save As dialogs now use QFileDialog.

Replacing the Page Delete and IO Error Dialogs

The Page Delete dialog is created and used in actions.c. We need to migrate this file to C++. We rename it to actions.cpp, modify the project file and regenerate the Makefile.

The changes required to make actions.cpp compile are minimal. We need to wrap more C header files and global variables in an extern "C" block.

    extern "C" {
    #include <Exm/TabB.h>
    #include "page.h"

    extern Page pages[];
    // Widget editDialog = 0, deleteDialog = 0;

    void SetPage(int);
    void AdjustPages(int, int);
    void FixPages();
    void PageChange(Widget w, XtPointer i, XmNotebookCallbackStruct *cs);
    Page AllocPage();
    char* Trim(char*);
    extern void SaveDB(char*);

    extern Widget shell, textw, labelw, notebook;
    extern int maxpages, currentPage, modified;

We need to forward declare the NewPage(), DeletePage(), EditPage() and SaveIt() functions so that the compiler generates the correct symbols for these functions.

    void NewPage(Widget, XtPointer, XmPushButtonCallbackStruct *);
    void DeletePage(Widget, XtPointer, XmPushButtonCallbackStruct *);
    void EditPage(Widget, XtPointer, XmPushButtonCallbackStruct *);
    void SaveIt(Widget, char *, XmPushButtonCallbackStruct *);
    } // extern "C"

We need to fix a single invalid pointer cast.

        // XtFree((XtPointer) pages[currentPage]);
        XtFree((char *) pages[currentPage]);

And we need to change the variable named new to newstr in the Trim() function.

We can now change the DeletePage() function to use QMessageBox::information().

First, we need to make sure we include the proper header for QMessageBox.

    // Qt includes
    #include <qmessagebox.h>

The code for DeletePage() looks like this:

    void
    DeletePage(Widget, XtPointer client_data,
               XmPushButtonCallbackStruct *)
    {
      QWidget *toplevel = (QWidget *) client_data;
      int result =
        QMessageBox::information( toplevel, "Page Delete Dialog",
                                  "Do you want to delete this page?",
                                  QMessageBox::Yes, QMessageBox::No );
      if ( result != QMessageBox::Yes )
          return;

At this point in the code, the page should be deleted. The code to do this is in the DoDeletePage() function. We move the contents of DoDeletePage() to this point and remove the DoDeletePage() function completely.

Next, we change todo.cpp to pass the top-level QMotifWidget as the client_data tot he DeletePage() function.

      // XtAddCallback(selected_menu[SELECTED_DELETE], XmNactivateCallback,
      //               (XtCallbackProc) DeletePage, NULL);
      XtAddCallback(selected_menu[SELECTED_DELETE], XmNactivateCallback,
                    (XtCallbackProc) DeletePage, (XtPointer) &toplevel);

The IO Error dialog is created and used in io.c. We need to migrate this file to C++. We rename it to io.cpp, modify the project file and regenerate the Makefile.

The changes required to make io.cpp compile are minimal. We need to wrap more C header files and global variables in an extern "C" block.

    extern "C" {
    #include <Exm/TabB.h>
    #include "page.h"

    extern Widget notebook, textw, shell;
    Page pages[MAXPAGES];

    extern int currentPage;
    extern int modified;
    int maxpages;
    Page AllocPage();

We need to forward declare the ReadDB() and SaveDB() functions so that the compiler generates the correct symbols for these functions.

    void ReadDB(char*);
    void SaveDB(char*);
    } // extern "C"

The ParseNewLines() function needs to be converted to proper C++.

    /*
    void ParseNewLines(char *label)
    char * label;
    */
    void ParseNewLines(char *label)
    {
        /* look for "\n" and change in '\n' and compact */

The PrintWithNewLines() function also needs to be converted to proper C++.

    /*
    static void PrintWithNewLines(output, label)
    FILE * output;
    char * label;
    */
    static void PrintWithNewLines(FILE *output, char *label)
    {
        /* look for '\n' and print "\n" */

We can now change the ReadDB() and SaveDB() functions to use QMessageBox::warning().

First, we need to make sure we include the proper header for QMessageBox.

    // Qt includes
    #include <qmessagebox.h>

The code for ReadDB() looks like this:

      input = fopen(filename, "r");

      if (input == NULL && strncmp(filename,"untitled",8) != 0) {
        QString message = "Cannot access (%1) for reading";
        QMessageBox::warning( 0, "IO Error", message.arg(filename) );
      }

      /* Destroy current pages on reread */
    ...

The code for SaveDB() looks like this:

      if (access(filename, F_OK) == 0 &&
          access(filename, W_OK) != 0) {
        QString message = "Cannot access (%1) for writing";
        QMessageBox::warning( 0, "IO Error", message.arg(filename) );
        return;
      }

      /* Append a ~ to make the old filename */
    ...

After we build the project, the application runs and operates as expected. The difference is that the Page Delete and IO Error dialogs now use QMessageBox.

[ Previous: Preparing to Migrate the User Interface ] [ Home ] [ Next: Using Custom QDialogs ]

Publicité

Best Of

Actualités les plus lues

Semaine
Mois
Année

Le Qt Developer Network au hasard

Logo

Utiliser QML et QtWebKit avec PySide

Le Qt Developer Network est un réseau de développeurs Qt anglophone, où ils peuvent partager leur expérience sur le framework. Lire l'article.

Communauté

Ressources

Liens utiles

Contact

  • Vous souhaitez rejoindre la rédaction ou proposer un tutoriel, une traduction, une question... ? Postez dans le forum Contribuez ou contactez-nous par MP ou par email (voir en bas de page).

Qt dans le magazine

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