Table Of Contents

Previous topic

4. Managing a graphical interface with Qt

Next topic

6. Reading a file of shapes

Download

5. DrawQt

5.1. Step 1: installation (30 min)

As for the previous sessions (reading an image and Qt,) we need to:

  • create a new workarea DrawQt under your work directory Project,

  • fetch the initial version of the DrawQt code – called DrawQtBase – from the Enseignement repository:

    $> cd Project
    $> svn mkdir https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>/DrawQt/trunk -m "Added DrawQt project"
    $> svn mkdir https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>/DrawQt/branches -m "Added DrawQt project"
    $> svn mkdir https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>/DrawQt/tags -m "Added DrawQt project"
    $> svn co https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>/DrawQt/trunk DrawQt
    
    $> svn export https://svn.lal.in2p3.fr/projects/Enseignement/LAL-Info/tags/2011/DrawQtBase \
                  DrawQt
    

    Note

    svn export exports a project from a repository without retrieving the revisions management. Indeed, we’ll modify this code base and commit it back into our own svn repository.

  • commit your DrawQt directory into svn.

Head toward the presentation of the application.

_images/validate-step.jpg

Validate this step


5.2. Step 2: reading the documentation (10 min)

During this initial step, paramount for the proper understanding of the overall workings of the application, we’ll crawl thru some documentation.

  1. first, build the documentation of DrawQt in the same fashion than for the previous sessions: using doxygen,
  2. read the documentation in your browser,
  3. look for the WFrame class. It will play a central role in this session. Navigate thru the classes connected to this WFrame and try to grok the relationships between those.
_images/validate-step.jpg

Validate this step


5.3. Step 3: building the application (20 min)

In order to build the application, we need to properly configure CMT so the tool knows where to find the sources, headers, etc...

Note

This configuration step wasn’t mandatory for the other sessions because our workarea was a directory created by CMT itself hence autoconfigured. (and this configuration step wasn’t necessary either for the documentation generation of step 2)

$> cmt config
$> source ./setup.sh

Then rebuild and run the application:

$> open ../app/DrawQt.app

This application is – for the moment – just a skeleton we’ll complete as we go along.

_images/validate-step.jpg

Validate this step


5.4. Step 4: reading an image (1h30)

Note

This step works you through the image reading implementation which has been written during the previous session.

To ease the implementation task, speed up the process and help you start on sane foundations, you are provided with a skeleton function. It is up to you to (correctly) complete it OR to re-use your own ReadFile code (copy paste it in place of the skeleton).

  1. The image reading functionality in DrawQt is named as in the image reading session: ReadFile(const std::string&). Helped by the DrawQt documentation, look for the class hosting that method and which method or function is calling that method. Then, compare its implementation with the one you wrote during the image reading session (and complete/amend your skeleton if necessary.)

  2. Test your application with the images stored under the Data directory. Some of the input files are purposedly corrupted: you’ll need to amend the Image::ReadFile(const std::string&) method to correctly handle (or print an error message) when dealing with such input data.

    • test 1: bad keyword
    • test 2: issue with the array filling (beware: program may crash!)

    To display a message in a small dialog box, use the very well documented method QMessageBox.

  3. once the tests are satisfactory, commit, remove all spurious printout messages and then commit again.

_images/validate-step.jpg

Validate this step


5.5. Step 5: support for an elliptical shape (1h30)

Note

The code you were provided with only handles rectangular shapes. In this exercize, a new Ellipse class will be implemented to deal with a new type of shape. This class will inherit from the class Shape.

  1. Create the files ellipse.h and ellipse.cpp. This class inherits from Shape so it also contains a data member m_box of type BoundingBox. This variable is sufficient to encode the properties of an ellipsis. It is therefore not needed to add any new data member to the class Ellipse.

  2. Update the cmt/requirements file so it knows about the ellipse.cpp file.

  3. Implement the methods of the class Shape which aren’t suitable for the class Ellipse. You can look at the Rectangle class for some inspiration. The Qt method allowing to draw an ellipse is documented here.

  4. Open the include/defs.h header file and modify it accordingly.

    Note

    enum SHAPE_TYPE is a type used for printing the name of a shape in a statistics box. There are rules to follow if you want the name of your shape to be correctly displayed. These rules are described in lines 75-100 of the file wstatistics.ui. This file is a graphical interface file generated by QtDesigner, a tool to create graphical user interfaces. Its format is XML. During the compilation, CMT takes this file as input and produces a proper C++ file (ui_wstatistics.h) which is fed back to the compiler.

  5. Implement the bool IsInside(int x, int y) method which will test if a given point falls inside the ellipse or not.

    Note

    Some formulae about ellipses can be found here.

    Note

    The origin point (0,0) of the frame is the top-left corner. Positive x go to the right. Positive y go down.

        (0,0) +-----------+ (xmax, 0)
              |           |
              |           |
              |           |
              |           |
              |           |
    (0, ymax) +-----------+ (xmax, ymax)
    
  6. Implement the method SumValues(Image *pData) and the other methods which need special treatment for an ellipse.

  7. Complete the Selection::AllocateShape(SHAPE_TYPE type) method so it can correctly handle the ellipse case.

  8. Add a button for the ellipse in WFrame. You can look at the Rectangle class for inspiration. An icon exists in the directory data/icons: Ellipse.bmp.

  9. Update the statistics, on the right in DrawQt if not already done.

  10. Do not forget to start with the correct ellipse formula and check the result...

_images/validate-step.jpg

Validate this step


5.6. Step 6: support for a square shape (1h)

Note

A square is a special case of a rectangle. The class Square will thus rather naturally inherit from the Rectangle class. We’ll just amend the method to update the shape to force the rectangle to have a width and a height of identical sizes.

  1. Create the files square.h and square.cpp. This class won’t need any new data member.
  2. Update the cmt/requirements file so it knows about square.cpp.
  3. Implement the methods of the class Rectangle which aren’t suitable for Square.
  4. Redefine ModifyEndShape(int lastMousePosition_x, int lastMousePosition_y) from Shape in the class Square to force m_box to stay square. This method is called for each and every mouse move during the painting of a shape. Look at the BoundingBox documentation, it could help you.

Note

You may want to use some mathematical functions in order to draw in all ways your square. max function is defined in std template algorithm, the abs function is defined in math library.

  1. Update the Selection::AllocateShape(SHAPE_TYPE type) method.
  2. Add a button for the square in WFrame. An icon is available: Square.bmp
  3. Update the statistics on the right in DrawQt if it hasn’t already been done.
_images/validate-step.jpg

Validate this step


5.7. Step 7: support for a circular shape (1h)

Note

A circle is a special case of an ellipse. The class Circle will thus rather naturally inherit from the Ellipse class. We’ll just amend the method to update the shape to force the ellipse to have a major and a minor axis of identical lengths.

  1. Create the files circle.cpp and circle.h. This class won’t need any new data member.
  2. Update the cmt/requirements file so it knows about circle.cpp.
  3. Implement the methods of the class Ellipse which aren’t suitable for Circle.
  4. Redefine ModifyEndShape(int x, int y) from Shape in the class Circle to force m_box to stay round. This method is called for each and every mouse move during the painting of a shape.
  5. Update the Selection::AllocateShape(SHAPE_TYPE type) method.
  6. Add a button for the square in WFrame. An icon is available: Circle.bmp
  7. Update the statistics on the right in DrawQt if it hasn’t already been done.
_images/validate-step.jpg

Validate this step


5.8. Step 8: make a tag for your current work

Note

At this step, you should have a simple drawQt application that your will improve after. Let’s Make a tag with this version. For more information about tag and branches, see the svn exercice

  1. Go back into your Project/DrawQt folder
$> svn cp . https://svn.lal.in2p3.fr/projects/Etudiants/ens<n>/DrawQt/tag/<enter your tag name here> -m "First version of DrawQt"
_images/validate-step.jpg

Validate this step