diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-08 12:31:36 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-08 12:31:36 -0600 |
commit | d796c9dd933ab96ec83b9a634feedd5d32e1ba3f (patch) | |
tree | 6e3dcca4f77e20ec8966c666aac7c35bd4704053 /doc/html/tutorial2-03.html | |
download | tqt3-d796c9dd933ab96ec83b9a634feedd5d32e1ba3f.tar.gz tqt3-d796c9dd933ab96ec83b9a634feedd5d32e1ba3f.zip |
Test conversion to TQt3 from Qt3 8c6fc1f8e35fd264dd01c582ca5e7549b32ab731
Diffstat (limited to 'doc/html/tutorial2-03.html')
-rw-r--r-- | doc/html/tutorial2-03.html | 298 |
1 files changed, 298 insertions, 0 deletions
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 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/doc/tutorial2.doc:110 --> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<title>Data Elements</title> +<style type="text/css"><!-- +fn { margin-left: 1cm; text-indent: -1cm; } +a:link { color: #004faf; text-decoration: none } +a:visited { color: #672967; text-decoration: none } +body { background: #ffffff; color: black; } +--></style> +</head> +<body> + +<table border="0" cellpadding="0" cellspacing="0" width="100%"> +<tr bgcolor="#E5E5E5"> +<td valign=center> + <a href="index.html"> +<font color="#004faf">Home</font></a> + | <a href="classes.html"> +<font color="#004faf">All Classes</font></a> + | <a href="mainclasses.html"> +<font color="#004faf">Main Classes</font></a> + | <a href="annotated.html"> +<font color="#004faf">Annotated</font></a> + | <a href="groups.html"> +<font color="#004faf">Grouped Classes</font></a> + | <a href="functions.html"> +<font color="#004faf">Functions</font></a> +</td> +<td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><h1 align=center>Data Elements</h1> + + +<p> +<p> We will use a C++ class called <tt>Element</tt> to provide storage and +access for data elements. +<p> (Extracts from <tt>element.h</tt>.) +<p> + +<pre> private: +</pre><pre> double m_value; + <a href="qcolor.html">TQColor</a> m_valueColor; + int m_valuePattern; + <a href="qstring.html">TQString</a> m_label; + <a href="qcolor.html">TQColor</a> m_labelColor; + double m_propoints[2 * MAX_PROPOINTS]; +</pre> +<p> 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 <tt>m_propoints</tt> array. +<p> + +<pre> #include <<a href="qcolor-h.html">qcolor.h</a>> + #include <<a href="qnamespace-h.html">qnamespace.h</a>> + #include <<a href="qstring-h.html">qstring.h</a>> + #include <<a href="qvaluevector-h.html">qvaluevector.h</a>> +</pre> +<p> Although the <tt>Element</tt> class is a purely internal data class, it +<tt>#include</tt>s 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 <a href="qcolor-h.html">qcolor.h</a> so that we can hold the +paint color and text color in the <tt>Element</tt> class. The use of <a href="qnamespace-h.html">qnamespace.h</a> is slightly obscure. Most TQt classes are derived from the +<a href="qt.html">TQt</a> superclass which contains various +enumerations. The <tt>Element</tt> class does not derive from <a href="qt.html">TQt</a>, so we need to include <a href="qnamespace-h.html">qnamespace.h</a> to have access to +the TQt enum names. An alternative approach would have been to have +made <tt>Element</tt> a <a href="qt.html">TQt</a> subclass. We include <a href="qstring-h.html">qstring.h</a> to make use of TQt's Unicode strings. As a convenience we +will <tt>typedef</tt> a vector container for <tt>Element</tt>s, which is why we +pull in the <a href="qvaluevector-h.html">qvaluevector.h</a> header. +<p> <pre> typedef TQValueVector<Element> ElementVector; +</pre> +<p> TQt provides a number of containers, some value based like +<a href="qvaluevector.html">TQValueVector</a>, and others pointer based. (See <a href="collection.html">Collection Classes</a>.) Here we've just typedefed one container +type; we will keep each data set of elements in one <tt>ElementVector</tt>. +<p> <pre> const double EPSILON = 0.0000001; // Must be > INVALID. +</pre> +<p> Elements may only have positive values. Because we hold values as +doubles we cannot readily compare them with zero. Instead we specify a +value, <tt>EPSILON</tt>, which is close to zero, and consider any value +greater than <tt>EPSILON</tt> to be positive and valid. +<p> <pre> class Element + { + public: + enum { INVALID = -1 }; + enum { NO_PROPORTION = -1 }; + enum { MAX_PROPOINTS = 3 }; // One proportional point per chart type +</pre> +<p> We define three public enums for <tt>Element</tt>s. <tt>INVALID</tt> is used by +the isValid() function. It is useful because we are going to use a +fixed size vector of <tt>Element</tt>s, and can mark unused <tt>Element</tt>s by +giving them <tt>INVALID</tt> values. The <tt>NO_PROPORTION</tt> 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. +<p> 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 <em>proportional</em> 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. +<p> The <tt>MAX_PROPOINTS</tt> 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 <tt>Element</tt> class is strongly coupled to the +number of chart types provided by the <tt>ChartForm</tt> 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. +<p> <pre> Element( double value = INVALID, TQColor valueColor = TQt::gray, + int valuePattern = TQt::SolidPattern, + const <a href="qstring.html">TQString</a>& label = <a href="qstring.html#TQString-null">TQString::null</a>, + <a href="qcolor.html">TQColor</a> labelColor = TQt::black ) { + init( value, valueColor, valuePattern, label, labelColor ); + for ( int i = 0; i < MAX_PROPOINTS * 2; ++i ) + m_propoints[i] = NO_PROPORTION; + } +</pre> +<p> The constructor provides default values for all members of the <tt>Element</tt> 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. +<p> <pre> bool isValid() const { return m_value > EPSILON; } +</pre> +<p> Since we are storing <tt>Element</tt>s 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. +<p> (Extracts from <tt>element.cpp</tt>.) +<p> + +<pre> double Element::proX( int index ) const + { + <a href="qapplication.html#Q_ASSERT">Q_ASSERT</a>(index >= 0 && index < MAX_PROPOINTS); + return m_propoints[2 * index]; + } +</pre> +<p> Getters and setters are provided for all the members of <tt>Element</tt>. +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 +<tt>Q_ASSERT</tt> macro to provide pre-condition tests on the chart type +index; (see <a href="debug.html">Debugging</a>). +<p> <h2> Reading and Writing Data Elements +</h2> +<a name="1"></a><p> (Extracts from <tt>element.h</tt>.) +<p> + +<pre> TQTextStream &operator<<( <a href="qtextstream.html">TQTextStream</a>&, const Element& ); + TQTextStream &operator>>( <a href="qtextstream.html">TQTextStream</a>&, Element& ); +</pre> +<p> To make our <tt>Element</tt> class more self-contained we provide overloads +for the << and >> operators so that <tt>Element</tt>s 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. +<p> (Extracts from <tt>element.cpp</tt>.) +<p> + +<pre> #include "element.h" + + #include <<a href="qstringlist-h.html">qstringlist.h</a>> + #include <<a href="qtextstream-h.html">qtextstream.h</a>> +</pre> +<p> Our implementation of the operators retquires the inclusion of <a href="qtextstream-h.html">qtextstream.h</a> and <a href="qstringlist-h.html">qstringlist.h</a>. +<p> <pre> const char FIELD_SEP = ':'; + const char PROPOINT_SEP = ';'; + const char XY_SEP = ','; +</pre> +<p> 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: +<pre> +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 +</pre> + +<p> There's no problem having whitespace and field separators in label +text due to the way we read <tt>Element</tt> data. +<p> <pre> TQTextStream &operator<<( <a href="qtextstream.html">TQTextStream</a> &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; + } +</pre> +<p> Writing elements is straight-forward. Each member is written followed +by a field separator. The points are written as comma separated (<tt>XY_SEP</tt>) x, y pairs, each pair separated by the <tt>PROPOINT_SEP</tt> +separator. The final field is the label followed by a newline. +<p> <pre> TQTextStream &operator>>( <a href="qtextstream.html">TQTextStream</a> &s, Element &element ) + { + <a name="x2553"></a> <a href="qstring.html">TQString</a> data = s.<a href="qtextstream.html#readLine">readLine</a>(); + element.setValue( Element::INVALID ); + + int errors = 0; + bool ok; + + <a name="x2552"></a> <a href="qstringlist.html">TQStringList</a> fields = TQStringList::<a href="qstringlist.html#split">split</a>( FIELD_SEP, data ); + <a name="x2555"></a> if ( fields.<a href="qvaluelist.html#count">count</a>() >= 4 ) { + double value = fields[0].toDouble( &ok ); + if ( !ok ) + errors++; + <a href="qcolor.html">TQColor</a> valueColor = TQColor( fields[1] ); + <a name="x2550"></a> if ( !valueColor.<a href="qcolor.html#isValid">isValid</a>() ) + errors++; + int valuePattern = fields[2].toInt( &ok ); + if ( !ok ) + errors++; + <a href="qcolor.html">TQColor</a> labelColor = TQColor( fields[3] ); + if ( !labelColor.<a href="qcolor.html#isValid">isValid</a>() ) + errors++; + <a href="qstringlist.html">TQStringList</a> propoints = TQStringList::<a href="qstringlist.html#split">split</a>( PROPOINT_SEP, fields[4] ); + <a name="x2551"></a> <a href="qstring.html">TQString</a> label = data.<a href="qstring.html#section">section</a>( FIELD_SEP, 5 ); + + if ( !errors ) { + element.set( value, valueColor, valuePattern, label, labelColor ); + int i = 0; + <a name="x2554"></a> for ( TQStringList::iterator point = propoints.<a href="qvaluelist.html#begin">begin</a>(); + <a name="x2556"></a> i < Element::MAX_PROPOINTS && point != propoints.<a href="qvaluelist.html#end">end</a>(); + ++i, ++point ) { + errors = 0; + <a href="qstringlist.html">TQStringList</a> xy = TQStringList::<a href="qstringlist.html#split">split</a>( 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; + } +</pre> +<p> To read an element we read one record (i.e. one line). We break the +data into fields using <a href="qstringlist.html#split">TQStringList::split</a>(). Because it is possible +that a label will contain <tt>FIELD_SEP</tt> characters we use +<a href="qstring.html#section">TQString::section</a>() 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 <tt>Element::set()</tt> to write this data into +the element; otherwise we leave the element <tt>INVALID</tt>. 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 <tt>NO_PROPORTION</tt>. +<p> Our <tt>Element</tt> 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. +<p> We are now ready to create <tt>main.cpp</tt> and the user interface through +which our users will create, edit and visualise their data sets. +<p> <center><table cellpadding="4" cellspacing="2" border="0"> +<tr bgcolor="#f0f0f0"> +<td valign="top">For more information on TQt's data streaming facilities see <a href="datastreamformat.html">TQDataStream Operators' Formats</a>, and see +the source code for any of the TQt classes mentioned that are similar +to what you want to store. +</table></center> +<p> <p align="right"> +<a href="tutorial2-02.html">« The 'Big Picture'</a> | +<a href="tutorial2.html">Contents</a> | +<a href="tutorial2-04.html">Mainly Easy »</a> +</p> +<p> +<!-- eof --> +<p><address><hr><div align=center> +<table width=100% cellspacing=0 border=0><tr> +<td>Copyright © 2007 +<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a> +<td align=right><div align=right>TQt 3.3.8</div> +</table></div></address></body> +</html> |