From d796c9dd933ab96ec83b9a634feedd5d32e1ba3f Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Tue, 8 Nov 2011 12:31:36 -0600 Subject: Test conversion to TQt3 from Qt3 8c6fc1f8e35fd264dd01c582ca5e7549b32ab731 --- doc/html/tutorial2-03.html | 298 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 doc/html/tutorial2-03.html (limited to 'doc/html/tutorial2-03.html') diff --git a/doc/html/tutorial2-03.html b/doc/html/tutorial2-03.html new file mode 100644 index 000000000..44b039ab8 --- /dev/null +++ b/doc/html/tutorial2-03.html @@ -0,0 +1,298 @@ + + + + + +Data Elements + + + + + + + +
+ +Home + | +All Classes + | +Main Classes + | +Annotated + | +Grouped Classes + | +Functions +

Data Elements

+ + +

+

We will use a C++ class called Element to provide storage and +access for data elements. +

(Extracts from element.h.) +

+ +

    private:
+
        double m_value;
+        TQColor m_valueColor;
+        int m_valuePattern;
+        TQString m_label;
+        TQColor m_labelColor;
+        double m_propoints[2 * MAX_PROPOINTS];
+
+

Each element has a value. Each value is displayed graphically with a +particular color and fill pattern. Values may have a label associated +with them; the label is drawn using the label color and for each type +of chart has a (relative) position stored in the m_propoints array. +

+ +

    #include <qcolor.h>
+    #include <qnamespace.h>
+    #include <qstring.h>
+    #include <qvaluevector.h>
+
+

Although the Element class is a purely internal data class, it +#includes four TQt classes. TQt is often perceived as a purely GUI +toolkit, but it provides many non-GUI classes to support most aspects +of application programming. We use qcolor.h so that we can hold the +paint color and text color in the Element class. The use of qnamespace.h is slightly obscure. Most TQt classes are derived from the +TQt superclass which contains various +enumerations. The Element class does not derive from TQt, so we need to include qnamespace.h to have access to +the TQt enum names. An alternative approach would have been to have +made Element a TQt subclass. We include qstring.h to make use of TQt's Unicode strings. As a convenience we +will typedef a vector container for Elements, which is why we +pull in the qvaluevector.h header. +

    typedef TQValueVector<Element> ElementVector;
+
+

TQt provides a number of containers, some value based like +TQValueVector, and others pointer based. (See Collection Classes.) Here we've just typedefed one container +type; we will keep each data set of elements in one ElementVector. +

    const double EPSILON = 0.0000001; // Must be > INVALID.
+
+

Elements may only have positive values. Because we hold values as +doubles we cannot readily compare them with zero. Instead we specify a +value, EPSILON, which is close to zero, and consider any value +greater than EPSILON to be positive and valid. +

    class Element
+    {
+    public:
+        enum { INVALID = -1 };
+        enum { NO_PROPORTION = -1 };
+        enum { MAX_PROPOINTS = 3 }; // One proportional point per chart type
+
+

We define three public enums for Elements. INVALID is used by +the isValid() function. It is useful because we are going to use a +fixed size vector of Elements, and can mark unused Elements by +giving them INVALID values. The NO_PROPORTION enum is used to +signify that the user has not positioned the Element's label; any +positive proportion value is taken to be the text element's position +proportional to the canvas's size. +

If we stored each label's actual x and y position, then every time the +user resized the main window (and therefore the canvas), the text +would retain its original (now incorrect) position. So instead of +storing absolute (x, y) positions we store proportional positions, +i.e. x/width and y/height. We can then multiply these positions by +the current width and height respectively when we come to draw the +text and the text will be positioned correctly regardless of any +resizing. For example, if a label has an x position of 300 and the +canvas is 400 pixels wide, the proportional x value is 300/400 = 0.75. +

The MAX_PROPOINTS enum is problematic. We need to store the x and y +proportions for the text label for every chart type. And we have +chosen to store these proportions in a fixed-size array. Because of +this we must specify the maximum number of proportion pairs needed. +This value must be changed if we change the number of chart types, +which means that the Element class is strongly coupled to the +number of chart types provided by the ChartForm class. In a +larger application we might have used a vector to store these points +and dynamically resized it depending on how many chart types are +available. +

        Element( double value = INVALID, TQColor valueColor = TQt::gray,
+                 int valuePattern = TQt::SolidPattern,
+                 const TQString& label = TQString::null,
+                 TQColor labelColor = TQt::black ) {
+            init( value, valueColor, valuePattern, label, labelColor );
+            for ( int i = 0; i < MAX_PROPOINTS * 2; ++i )
+                m_propoints[i] = NO_PROPORTION;
+        }
+
+

The constructor provides default values for all members of the Element class. New elements always have label text with no position. +We use an init() function because we also provide a set() function +which works like the constructor apart from leaving the proportional +positions alone. +

        bool isValid() const { return m_value > EPSILON; }
+
+

Since we are storing Elements in a fixed size vector we need to be +able to check whether a particular element is valid (i.e. should be +used in calculations and displayed) or not. This is easily achieved +with the isValid() function. +

(Extracts from element.cpp.) +

+ +

    double Element::proX( int index ) const
+    {
+        Q_ASSERT(index >= 0 && index < MAX_PROPOINTS);
+        return m_propoints[2 * index];
+    }
+
+

Getters and setters are provided for all the members of Element. +The proX() and proY() getters and the setProX() and setProY() setters +take an index which identifies the type of chart the proportional +position applies to. This means that the user can have labels +positioned separately for the same data set for a vertical bar chart, +a horizontal bar chart and for a pie chart. Note also that we use the +Q_ASSERT macro to provide pre-condition tests on the chart type +index; (see Debugging). +

Reading and Writing Data Elements +

+

(Extracts from element.h.) +

+ +

    TQTextStream &operator<<( TQTextStream&, const Element& );
+    TQTextStream &operator>>( TQTextStream&, Element& );
+
+

To make our Element class more self-contained we provide overloads +for the << and >> operators so that Elements may be written to +and read from text streams. We could just as easily have used binary +streams, but using text makes it possible for users to manipulate +their data using a text editor and makes it easier to generate and +filter the data using a scripting language. +

(Extracts from element.cpp.) +

+ +

    #include "element.h"
+
+    #include <qstringlist.h>
+    #include <qtextstream.h>
+
+

Our implementation of the operators retquires the inclusion of qtextstream.h and qstringlist.h. +

    const char FIELD_SEP = ':';
+    const char PROPOINT_SEP = ';';
+    const char XY_SEP = ',';
+
+

The format we are using to store the data is colon separated fields +and newline separated records. The proportional points are semi-colon +separated, with their x, y pairs being comma separated. The field +order is value, value color, value pattern, label color, label points, +label text. For example: +

+20:#ff0000:14:#000000:0.767033,0.412946;0,0.75;0,0:Red :with colons:!
+70:#00ffff:2:#ffff00:0.450549,0.198661;0.198516,0.125954;0,0.198473:Cyan
+35:#0000ff:8:#555500:0.10989,0.299107;0.397032,0.562977;0,0.396947:Blue
+55:#ffff00:1:#000080:0.0989011,0.625;0.595547,0.312977;0,0.59542:Yellow
+80:#ff00ff:1:#000000:0.518681,0.694196;0.794063,0;0,0.793893:Magenta or Violet
+
+ +

There's no problem having whitespace and field separators in label +text due to the way we read Element data. +

    TQTextStream &operator<<( TQTextStream &s, const Element &element )
+    {
+        s << element.value() << FIELD_SEP
+          << element.valueColor().name() << FIELD_SEP
+          << element.valuePattern() << FIELD_SEP
+          << element.labelColor().name() << FIELD_SEP;
+
+        for ( int i = 0; i < Element::MAX_PROPOINTS; ++i ) {
+            s << element.proX( i ) << XY_SEP << element.proY( i );
+            s << ( i == Element::MAX_PROPOINTS - 1 ? FIELD_SEP : PROPOINT_SEP );
+        }
+
+        s << element.label() << '\n';
+
+        return s;
+    }
+
+

Writing elements is straight-forward. Each member is written followed +by a field separator. The points are written as comma separated (XY_SEP) x, y pairs, each pair separated by the PROPOINT_SEP +separator. The final field is the label followed by a newline. +

    TQTextStream &operator>>( TQTextStream &s, Element &element )
+    {
+        TQString data = s.readLine();
+        element.setValue( Element::INVALID );
+
+        int errors = 0;
+        bool ok;
+
+        TQStringList fields = TQStringList::split( FIELD_SEP, data );
+        if ( fields.count() >= 4 ) {
+            double value = fields[0].toDouble( &ok );
+            if ( !ok )
+                errors++;
+            TQColor valueColor = TQColor( fields[1] );
+            if ( !valueColor.isValid() )
+                errors++;
+            int valuePattern = fields[2].toInt( &ok );
+            if ( !ok )
+                errors++;
+            TQColor labelColor = TQColor( fields[3] );
+            if ( !labelColor.isValid() )
+                errors++;
+            TQStringList propoints = TQStringList::split( PROPOINT_SEP, fields[4] );
+            TQString label = data.section( FIELD_SEP, 5 );
+
+            if ( !errors ) {
+                element.set( value, valueColor, valuePattern, label, labelColor );
+                int i = 0;
+                for ( TQStringList::iterator point = propoints.begin();
+                    i < Element::MAX_PROPOINTS && point != propoints.end();
+                    ++i, ++point ) {
+                    errors = 0;
+                    TQStringList xy = TQStringList::split( XY_SEP, *point );
+                    double x = xy[0].toDouble( &ok );
+                    if ( !ok || x <= 0.0 || x >= 1.0 )
+                        errors++;
+                    double y = xy[1].toDouble( &ok );
+                    if ( !ok || y <= 0.0 || y >= 1.0 )
+                        errors++;
+                    if ( errors )
+                        x = y = Element::NO_PROPORTION;
+                    element.setProX( i, x );
+                    element.setProY( i, y );
+                }
+            }
+        }
+
+        return s;
+    }
+
+

To read an element we read one record (i.e. one line). We break the +data into fields using TQStringList::split(). Because it is possible +that a label will contain FIELD_SEP characters we use +TQString::section() to extract all the text from the last field to the +end of the line. If there are enough fields and the value, colors and +pattern data is valid we use Element::set() to write this data into +the element; otherwise we leave the element INVALID. We then +iterate through the points. If the x and y proportions are valid and +in range we set them for the element. If one or both proportions is +invalid they will hold the value zero; this is not suitable so we +change invalid (and out-of-range) proportional point values to NO_PROPORTION. +

Our Element class is now sufficient to store, manipulate, read and +write element data. We have also created an element vector typedef for +storing a collection of elements. +

We are now ready to create main.cpp and the user interface through +which our users will create, edit and visualise their data sets. +

+ +
For more information on TQt's data streaming facilities see TQDataStream Operators' Formats, and see +the source code for any of the TQt classes mentioned that are similar +to what you want to store. +
+

+« The 'Big Picture' | +Contents | +Mainly Easy » +

+

+ +


+ +
Copyright © 2007 +TrolltechTrademarks +
TQt 3.3.8
+
+ -- cgit v1.2.3