|  | @@ -22,7 +22,7 @@
 | 
		
	
		
			
			| 22 | 22 |  \mark{\noexpand\nullsec0{A Note on Notation}}
 | 
		
	
		
			
			| 23 | 23 |  \def\pn{Typica}
 | 
		
	
		
			
			| 24 | 24 |  \def\filebase{typica}
 | 
		
	
		
			
			| 25 |  | -\def\version{1.4.3 \number\year-\number\month-\number\day}
 | 
		
	
		
			
			|  | 25 | +\def\version{1.5 \number\year-\number\month-\number\day}
 | 
		
	
		
			
			| 26 | 26 |  \def\years{2007--2013}
 | 
		
	
		
			
			| 27 | 27 |  \def\title{\pn{} (Version \version)}
 | 
		
	
		
			
			| 28 | 28 |  \newskip\dangerskipb
 | 
		
	
	
		
			
			|  | @@ -60,10 +60,10 @@
 | 
		
	
		
			
			| 60 | 60 |  	distribute, sublicense, and/or sell copies of the Software, and to permit
 | 
		
	
		
			
			| 61 | 61 |  	persons to whom the Software is furnished to do so, subject to the following
 | 
		
	
		
			
			| 62 | 62 |  	conditions:\medskip
 | 
		
	
		
			
			| 63 |  | -	
 | 
		
	
		
			
			|  | 63 | +
 | 
		
	
		
			
			| 64 | 64 |  	The above copyright notice and this permission notice shall be included in
 | 
		
	
		
			
			| 65 | 65 |  	all copies or substantial portions of the Software.\medskip
 | 
		
	
		
			
			| 66 |  | -	
 | 
		
	
		
			
			|  | 66 | +
 | 
		
	
		
			
			| 67 | 67 |  	THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
		
	
		
			
			| 68 | 68 |  	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
		
	
		
			
			| 69 | 69 |  	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
		
	
	
		
			
			|  | @@ -71,24 +71,24 @@
 | 
		
	
		
			
			| 71 | 71 |  	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
		
	
		
			
			| 72 | 72 |  	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 | 
		
	
		
			
			| 73 | 73 |  	IN THE SOFTWARE.
 | 
		
	
		
			
			| 74 |  | -	
 | 
		
	
		
			
			|  | 74 | +
 | 
		
	
		
			
			| 75 | 75 |  	\bigskip\noindent Parts of \pn{} are from QextSerialPort which is used under the
 | 
		
	
		
			
			| 76 | 76 |  	MIT license as follows:
 | 
		
	
		
			
			| 77 |  | -	
 | 
		
	
		
			
			|  | 77 | +
 | 
		
	
		
			
			| 78 | 78 |  	\bigskip\noindent Copyright \copyright\ 2000--2003 Wayne Roth
 | 
		
	
		
			
			| 79 |  | -	
 | 
		
	
		
			
			|  | 79 | +
 | 
		
	
		
			
			| 80 | 80 |      \noindent Copyright \copyright\ 2004--2007 Stefan Sander
 | 
		
	
		
			
			| 81 |  | -    
 | 
		
	
		
			
			|  | 81 | +
 | 
		
	
		
			
			| 82 | 82 |  	\noindent Copyright \copyright\ 2007 Michal Policht
 | 
		
	
		
			
			| 83 |  | -    
 | 
		
	
		
			
			|  | 83 | +
 | 
		
	
		
			
			| 84 | 84 |  	\noindent Copyright \copyright\ 2008 Brandon Fosdick
 | 
		
	
		
			
			| 85 |  | -    
 | 
		
	
		
			
			|  | 85 | +
 | 
		
	
		
			
			| 86 | 86 |  	\noindent Copyright \copyright\ 2009--2010 Liam Staskawicz
 | 
		
	
		
			
			| 87 |  | -    
 | 
		
	
		
			
			|  | 87 | +
 | 
		
	
		
			
			| 88 | 88 |  	\noindent Copyright \copyright\ 2011 Debao Zhang
 | 
		
	
		
			
			| 89 |  | -    
 | 
		
	
		
			
			|  | 89 | +
 | 
		
	
		
			
			| 90 | 90 |      \bigskip\noindent Web: http://code.google.com/p/qextserialport/
 | 
		
	
		
			
			| 91 |  | -    
 | 
		
	
		
			
			|  | 91 | +
 | 
		
	
		
			
			| 92 | 92 |      \bigskip\noindent Permission is hereby granted, free of charge, to any person obtaining
 | 
		
	
		
			
			| 93 | 93 |      a copy of this software and associated documentation files (the
 | 
		
	
		
			
			| 94 | 94 |      ``Software''), to deal in the Software without restriction, including
 | 
		
	
	
		
			
			|  | @@ -96,10 +96,10 @@
 | 
		
	
		
			
			| 96 | 96 |      distribute, sublicense, and/or sell copies of the Software, and to
 | 
		
	
		
			
			| 97 | 97 |      permit persons to whom the Software is furnished to do so, subject to
 | 
		
	
		
			
			| 98 | 98 |      the following conditions:
 | 
		
	
		
			
			| 99 |  | -    
 | 
		
	
		
			
			|  | 99 | +
 | 
		
	
		
			
			| 100 | 100 |      The above copyright notice and this permission notice shall be
 | 
		
	
		
			
			| 101 | 101 |      included in all copies or substantial portions of the Software.
 | 
		
	
		
			
			| 102 |  | -    
 | 
		
	
		
			
			|  | 102 | +
 | 
		
	
		
			
			| 103 | 103 |      THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
 | 
		
	
		
			
			| 104 | 104 |      EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
		
	
		
			
			| 105 | 105 |      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
		
	
	
		
			
			|  | @@ -833,6 +833,7 @@ generated file empty.
 | 
		
	
		
			
			| 833 | 833 |  @<LinearSplineInterpolator Implementation@>@/
 | 
		
	
		
			
			| 834 | 834 |  @<LinearSplineInterpolationConfWidget implementation@>@/
 | 
		
	
		
			
			| 835 | 835 |  @<TranslationConfWidget implementation@>@/
 | 
		
	
		
			
			|  | 836 | +@<FreeAnnotationConfWidget implementation@>@/
 | 
		
	
		
			
			| 836 | 837 |  
 | 
		
	
		
			
			| 837 | 838 |  @ A few headers are required for various parts of \pn{}. These allow the use of
 | 
		
	
		
			
			| 838 | 839 |  various Qt modules.
 | 
		
	
	
		
			
			|  | @@ -1141,7 +1142,7 @@ settings and restoring the window geometry from these settings.
 | 
		
	
		
			
			| 1141 | 1142 |  
 | 
		
	
		
			
			| 1142 | 1143 |  As of version 1.4 window geometry management is provided for all windows. The
 | 
		
	
		
			
			| 1143 | 1144 |  |restoreSizeAndPosition()| and |saveSizeAndPosition()| methods should be
 | 
		
	
		
			
			| 1144 |  | -considered depreciated. 
 | 
		
	
		
			
			|  | 1145 | +considered depreciated.
 | 
		
	
		
			
			| 1145 | 1146 |  
 | 
		
	
		
			
			| 1146 | 1147 |  @<Class declarations@>=
 | 
		
	
		
			
			| 1147 | 1148 |  class ScriptQMainWindow : public QMainWindow@/
 | 
		
	
	
		
			
			|  | @@ -1709,7 +1710,7 @@ QScriptValue constructQBoxLayout(QScriptContext *context,
 | 
		
	
		
			
			| 1709 | 1710 |  void setQBoxLayoutProperties(QScriptValue value, QScriptEngine *engine);
 | 
		
	
		
			
			| 1710 | 1711 |  QScriptValue QBoxLayout_addLayout(QScriptContext *context, QScriptEngine *engine);
 | 
		
	
		
			
			| 1711 | 1712 |  QScriptValue QBoxLayout_addWidget(QScriptContext *context, QScriptEngine *engine);
 | 
		
	
		
			
			| 1712 |  | -								  
 | 
		
	
		
			
			|  | 1713 | +
 | 
		
	
		
			
			| 1713 | 1714 |  @ The script constructor must be passed to the scripting engine.
 | 
		
	
		
			
			| 1714 | 1715 |  
 | 
		
	
		
			
			| 1715 | 1716 |  @<Set up the scripting engine@>=
 | 
		
	
	
		
			
			|  | @@ -1815,7 +1816,7 @@ QScriptValue QBoxLayout_addWidget(QScriptContext *context, QScriptEngine *)
 | 
		
	
		
			
			| 1815 | 1816 |  \noindent The |QAction| class is used in \pn{} to create menu items and respond
 | 
		
	
		
			
			| 1816 | 1817 |  to the selection of these items. Three functions are required for our scripting
 | 
		
	
		
			
			| 1817 | 1818 |  needs with regard to this class.
 | 
		
	
		
			
			| 1818 |  | -								  
 | 
		
	
		
			
			|  | 1819 | +
 | 
		
	
		
			
			| 1819 | 1820 |  @<Function prototypes for scripting@>=
 | 
		
	
		
			
			| 1820 | 1821 |  QScriptValue constructQAction(QScriptContext *context, QScriptEngine *engine);
 | 
		
	
		
			
			| 1821 | 1822 |  QScriptValue QAction_setShortcut(QScriptContext *context,
 | 
		
	
	
		
			
			|  | @@ -1945,7 +1946,7 @@ QScriptValue QFileDialog_getSaveFileName(QScriptContext *context,
 | 
		
	
		
			
			| 1945 | 1946 |  			retval = QScriptValue(engine,
 | 
		
	
		
			
			| 1946 | 1947 |  							      QFileDialog::getSaveFileName(widget, caption,
 | 
		
	
		
			
			| 1947 | 1948 |  								                               dir, "", 0, 0));
 | 
		
	
		
			
			| 1948 |  | -		
 | 
		
	
		
			
			|  | 1949 | +
 | 
		
	
		
			
			| 1949 | 1950 |  			setQFileDialogProperties(retval, engine);
 | 
		
	
		
			
			| 1950 | 1951 |  		}
 | 
		
	
		
			
			| 1951 | 1952 |  		else
 | 
		
	
	
		
			
			|  | @@ -3168,7 +3169,7 @@ are not created directly.
 | 
		
	
		
			
			| 3168 | 3169 |  @<Function prototypes for scripting@>=
 | 
		
	
		
			
			| 3169 | 3170 |  void setQAbstractScrollAreaProperties(QScriptValue value,
 | 
		
	
		
			
			| 3170 | 3171 |                                        QScriptEngine *engine);
 | 
		
	
		
			
			| 3171 |  | -									  
 | 
		
	
		
			
			|  | 3172 | +
 | 
		
	
		
			
			| 3172 | 3173 |  @ The implementation of this is simple.
 | 
		
	
		
			
			| 3173 | 3174 |  
 | 
		
	
		
			
			| 3174 | 3175 |  @<Functions for scripting@>=
 | 
		
	
	
		
			
			|  | @@ -3494,7 +3495,7 @@ QScriptValue setFont(QScriptContext *context, QScriptEngine *engine);
 | 
		
	
		
			
			| 3494 | 3495 |  QScriptValue annotationFromRecord(QScriptContext *context,
 | 
		
	
		
			
			| 3495 | 3496 |                                    QScriptEngine *engine);
 | 
		
	
		
			
			| 3496 | 3497 |  QScriptValue setTabOrder(QScriptContext *context, QScriptEngine *engine);
 | 
		
	
		
			
			| 3497 |  | -									
 | 
		
	
		
			
			|  | 3498 | +
 | 
		
	
		
			
			| 3498 | 3499 |  @ These functions are passed to the scripting engine.
 | 
		
	
		
			
			| 3499 | 3500 |  
 | 
		
	
		
			
			| 3500 | 3501 |  @<Set up the scripting engine@>=
 | 
		
	
	
		
			
			|  | @@ -3771,7 +3772,7 @@ and reorganized.\endanger
 | 
		
	
		
			
			| 3771 | 3772 |  
 | 
		
	
		
			
			| 3772 | 3773 |  @<Function prototypes for scripting@>=
 | 
		
	
		
			
			| 3773 | 3774 |  QScriptValue createWindow(QScriptContext *context, QScriptEngine *engine);
 | 
		
	
		
			
			| 3774 |  | -void addLayoutToWidget(QDomElement element, QStack<QWidget*> *widgetStack, 
 | 
		
	
		
			
			|  | 3775 | +void addLayoutToWidget(QDomElement element, QStack<QWidget*> *widgetStack,
 | 
		
	
		
			
			| 3775 | 3776 |                         QStack<QLayout*> *layoutStack);
 | 
		
	
		
			
			| 3776 | 3777 |  void addLayoutToLayout(QDomElement element, QStack<QWidget *> *widgetStack,
 | 
		
	
		
			
			| 3777 | 3778 |                         QStack<QLayout *> *layoutStack);
 | 
		
	
	
		
			
			|  | @@ -4046,7 +4047,7 @@ are supported. The first two resolve to |QBoxLayout| layouts, {\tt grid}
 | 
		
	
		
			
			| 4046 | 4047 |  resolves to a |QGridLayout|, and {\tt stack} resolves to a |QStackedLayout|.
 | 
		
	
		
			
			| 4047 | 4048 |  
 | 
		
	
		
			
			| 4048 | 4049 |  @<Functions for scripting@>=
 | 
		
	
		
			
			| 4049 |  | -void addLayoutToWidget(QDomElement element, QStack<QWidget*> *widgetStack, 
 | 
		
	
		
			
			|  | 4050 | +void addLayoutToWidget(QDomElement element, QStack<QWidget*> *widgetStack,
 | 
		
	
		
			
			| 4050 | 4051 |                         QStack<QLayout*> *layoutStack)
 | 
		
	
		
			
			| 4051 | 4052 |  {
 | 
		
	
		
			
			| 4052 | 4053 |  	if(element.hasAttribute("type"))
 | 
		
	
	
		
			
			|  | @@ -7413,7 +7414,7 @@ QScriptValue constructMeasurementTimeOffset(QScriptContext *context,@|
 | 
		
	
		
			
			| 7413 | 7414 |                                              QScriptEngine *engine);
 | 
		
	
		
			
			| 7414 | 7415 |  void setMeasurementTimeOffsetProperties(QScriptValue value,
 | 
		
	
		
			
			| 7415 | 7416 |                                          QScriptEngine *engine);
 | 
		
	
		
			
			| 7416 |  | -										   
 | 
		
	
		
			
			|  | 7417 | +
 | 
		
	
		
			
			| 7417 | 7418 |  @ The scripting engine must be informed of the constructor.
 | 
		
	
		
			
			| 7418 | 7419 |  
 | 
		
	
		
			
			| 7419 | 7420 |  @<Set up the scripting engine@>=
 | 
		
	
	
		
			
			|  | @@ -8782,7 +8783,7 @@ QScriptValue ZoomLog_lastTime(QScriptContext *context, QScriptEngine *engine)
 | 
		
	
		
			
			| 8782 | 8783 |  	ZoomLog *self = getself<@[ZoomLog *@]>(context);
 | 
		
	
		
			
			| 8783 | 8784 |  	return QScriptValue(engine, self->lastTime(argument<int>(0, context)));
 | 
		
	
		
			
			| 8784 | 8785 |  }
 | 
		
	
		
			
			| 8785 |  | -		
 | 
		
	
		
			
			|  | 8786 | +
 | 
		
	
		
			
			| 8786 | 8787 |  @* A model for roasting data.
 | 
		
	
		
			
			| 8787 | 8788 |  
 | 
		
	
		
			
			| 8788 | 8789 |  \noindent Qt provides a tool called the model view architecture. This provides a
 | 
		
	
	
		
			
			|  | @@ -8914,7 +8915,7 @@ void MeasurementModel::newMeasurement(Measurement measure, int tempcolumn)
 | 
		
	
		
			
			| 8914 | 8915 |  	emit rowChanged(insertion);
 | 
		
	
		
			
			| 8915 | 8916 |  	delete temp;
 | 
		
	
		
			
			| 8916 | 8917 |  }
 | 
		
	
		
			
			| 8917 |  | -	
 | 
		
	
		
			
			|  | 8918 | +
 | 
		
	
		
			
			| 8918 | 8919 |  @ To find the insertion point for new measurements we use a binary search of the
 | 
		
	
		
			
			| 8919 | 8920 |  existing data. The code below is a direct adaptation of Program B\nfnote{%
 | 
		
	
		
			
			| 8920 | 8921 |  \underbar{The Art of Computer Programming} Volume 3 Sorting and Searching 2nd
 | 
		
	
	
		
			
			|  | @@ -9404,7 +9405,7 @@ QVariant MeasurementModel::data(const QModelIndex &index, int role) const@/
 | 
		
	
		
			
			| 9404 | 9405 |  					default:
 | 
		
	
		
			
			| 9405 | 9406 |  						break;
 | 
		
	
		
			
			| 9406 | 9407 |  				}
 | 
		
	
		
			
			| 9407 |  | -			} 
 | 
		
	
		
			
			|  | 9408 | +			}
 | 
		
	
		
			
			| 9408 | 9409 |  			return QVariant(row->at(index.column()).toString());
 | 
		
	
		
			
			| 9409 | 9410 |  		}
 | 
		
	
		
			
			| 9410 | 9411 |  	}
 | 
		
	
	
		
			
			|  | @@ -9757,7 +9758,7 @@ because there were no shops in Racine that could sell a simple dual digital
 | 
		
	
		
			
			| 9757 | 9758 |  count up timer at a time when my first timer was malfunctioning. After
 | 
		
	
		
			
			| 9758 | 9759 |  attempting to purchase a replacement device at several stores that have sold
 | 
		
	
		
			
			| 9759 | 9760 |  such devices in the past, I decided to spend a couple hours writing my own
 | 
		
	
		
			
			| 9760 |  | -timer. 
 | 
		
	
		
			
			|  | 9761 | +timer.
 | 
		
	
		
			
			| 9761 | 9762 |  
 | 
		
	
		
			
			| 9762 | 9763 |  For historical reasons, the |TimerDisplay| class is considerably more functional
 | 
		
	
		
			
			| 9763 | 9764 |  than \pn{} requires. Those needing only a digital timer can extract the code for
 | 
		
	
	
		
			
			|  | @@ -10207,7 +10208,7 @@ class PackLayout : public QLayout@/
 | 
		
	
		
			
			| 10207 | 10208 |  };
 | 
		
	
		
			
			| 10208 | 10209 |  
 | 
		
	
		
			
			| 10209 | 10210 |  @ The interesting portion of this class is in |doLayout()|. This function goes
 | 
		
	
		
			
			| 10210 |  | -over the items in the layout and sets the geometry appropriately. 
 | 
		
	
		
			
			|  | 10211 | +over the items in the layout and sets the geometry appropriately.
 | 
		
	
		
			
			| 10211 | 10212 |  
 | 
		
	
		
			
			| 10212 | 10213 |  The seemingly odd choice of returning |y| at the end of this function (indeed of
 | 
		
	
		
			
			| 10213 | 10214 |  having a return value at all) is to allow this function to provide the return
 | 
		
	
	
		
			
			|  | @@ -10536,7 +10537,7 @@ WidgetDecorator::WidgetDecorator(QWidget *widget, const QString &labeltext,
 | 
		
	
		
			
			| 10536 | 10537 |  	@<Adjust the decoration width@>@;
 | 
		
	
		
			
			| 10537 | 10538 |  	@<Pack widgets into the layout@>@;
 | 
		
	
		
			
			| 10538 | 10539 |  }
 | 
		
	
		
			
			| 10539 |  | -	
 | 
		
	
		
			
			|  | 10540 | +
 | 
		
	
		
			
			| 10540 | 10541 |  @ The decoration is a |QGraphicsView|. To get this to look right, we need to
 | 
		
	
		
			
			| 10541 | 10542 |  make sure there aren't any scroll bars and there shouldn't be a frame
 | 
		
	
		
			
			| 10542 | 10543 |  surrounding it. While we're at it, we allow it to accept clicks, though this
 | 
		
	
	
		
			
			|  | @@ -12368,16 +12369,16 @@ int main(int argc, char **argv)@/
 | 
		
	
		
			
			| 12368 | 12369 |  	Application app(*c, argv);
 | 
		
	
		
			
			| 12369 | 12370 |  	@<Set up icons@>@;
 | 
		
	
		
			
			| 12370 | 12371 |  	@<Set up fonts@>@;
 | 
		
	
		
			
			| 12371 |  | -	
 | 
		
	
		
			
			|  | 12372 | +
 | 
		
	
		
			
			| 12372 | 12373 |  	QSettings settings;
 | 
		
	
		
			
			| 12373 |  | -	
 | 
		
	
		
			
			|  | 12374 | +
 | 
		
	
		
			
			| 12374 | 12375 |  	@<Register device configuration widgets@>@;
 | 
		
	
		
			
			| 12375 | 12376 |  	@<Prepare the database connection@>@;
 | 
		
	
		
			
			| 12376 | 12377 |  	@<Load the application configuration@>@;
 | 
		
	
		
			
			| 12377 | 12378 |  	@<Set up the scripting engine@>@;
 | 
		
	
		
			
			| 12378 | 12379 |  	app.engine = engine;
 | 
		
	
		
			
			| 12379 | 12380 |  	@<Find and evaluate starting script@>@;
 | 
		
	
		
			
			| 12380 |  | -	
 | 
		
	
		
			
			|  | 12381 | +
 | 
		
	
		
			
			| 12381 | 12382 |  	int retval = app.exec();
 | 
		
	
		
			
			| 12382 | 12383 |  	delete engine;
 | 
		
	
		
			
			| 12383 | 12384 |  	return retval;@/
 | 
		
	
	
		
			
			|  | @@ -13216,7 +13217,7 @@ QScriptValue QTextEdit_print(QScriptContext *context, QScriptEngine *)
 | 
		
	
		
			
			| 13216 | 13217 |  	QTextEdit *self = getself<QTextEdit *>(context);
 | 
		
	
		
			
			| 13217 | 13218 |  	QTextDocument *document = self->document();
 | 
		
	
		
			
			| 13218 | 13219 |  	QPrinter printer;
 | 
		
	
		
			
			| 13219 |  | -	
 | 
		
	
		
			
			|  | 13220 | +
 | 
		
	
		
			
			| 13220 | 13221 |  	QPrintDialog printwindow(&printer, self);
 | 
		
	
		
			
			| 13221 | 13222 |  	if(printwindow.exec() != QDialog::Accepted)
 | 
		
	
		
			
			| 13222 | 13223 |  	{
 | 
		
	
	
		
			
			|  | @@ -14580,7 +14581,7 @@ QScriptValue QAbstractItemModel_data(QScriptContext *context, QScriptEngine *eng
 | 
		
	
		
			
			| 14580 | 14581 |  QScriptValue QAbstractItemModel_index(QScriptContext *context, QScriptEngine *engine);
 | 
		
	
		
			
			| 14581 | 14582 |  QScriptValue QAbstractItemModel_rowCount(QScriptContext *context, QScriptEngine *engine);
 | 
		
	
		
			
			| 14582 | 14583 |  QScriptValue QAbstractItemModel_hasChildren(QScriptContext *context, QScriptEngine *engine);
 | 
		
	
		
			
			| 14583 |  | -	
 | 
		
	
		
			
			|  | 14584 | +
 | 
		
	
		
			
			| 14584 | 14585 |  @ The constructor is trivial.
 | 
		
	
		
			
			| 14585 | 14586 |  
 | 
		
	
		
			
			| 14586 | 14587 |  @<Functions for scripting@>=
 | 
		
	
	
		
			
			|  | @@ -15149,15 +15150,21 @@ RoasterConfWidget::RoasterConfWidget(DeviceTreeModel *model, const QModelIndex &
 | 
		
	
		
			
			| 15149 | 15150 |  	NodeInserter *basicButtonInserter = new NodeInserter(tr("Annotation Button"), tr("Annotation Button"), "annotationbutton");
 | 
		
	
		
			
			| 15150 | 15151 |  	NodeInserter *countingButtonInserter = new NodeInserter(tr("Counting Button"), tr("Counting Button"), "reconfigurablebutton");
 | 
		
	
		
			
			| 15151 | 15152 |  	NodeInserter *spinBoxInserter = new NodeInserter(tr("Numeric Entry"), tr("Numeric Entry"), "annotationspinbox");
 | 
		
	
		
			
			|  | 15153 | +	NodeInserter *freeAnnotationInserter = new NodeInserter(tr("Free Text"),
 | 
		
	
		
			
			|  | 15154 | +	                                                        tr("Free Text"),
 | 
		
	
		
			
			|  | 15155 | +	                                                        "freeannotation");
 | 
		
	
		
			
			| 15152 | 15156 |  	annotationMenu->addAction(basicButtonInserter);
 | 
		
	
		
			
			| 15153 | 15157 |  	annotationMenu->addAction(countingButtonInserter);
 | 
		
	
		
			
			| 15154 | 15158 |  	annotationMenu->addAction(spinBoxInserter);
 | 
		
	
		
			
			|  | 15159 | +	annotationMenu->addAction(freeAnnotationInserter);
 | 
		
	
		
			
			| 15155 | 15160 |  	connect(basicButtonInserter, SIGNAL(triggered(QString, QString)),
 | 
		
	
		
			
			| 15156 | 15161 |  	        this, SLOT(insertChildNode(QString, QString)));
 | 
		
	
		
			
			| 15157 | 15162 |  	connect(countingButtonInserter, SIGNAL(triggered(QString, QString)),
 | 
		
	
		
			
			| 15158 | 15163 |  	        this, SLOT(insertChildNode(QString, QString)));
 | 
		
	
		
			
			| 15159 | 15164 |  	connect(spinBoxInserter, SIGNAL(triggered(QString, QString)),
 | 
		
	
		
			
			| 15160 | 15165 |  	        this, SLOT(insertChildNode(QString, QString)));
 | 
		
	
		
			
			|  | 15166 | +	connect(freeAnnotationInserter, SIGNAL(triggered(QString, QString)),
 | 
		
	
		
			
			|  | 15167 | +	        this, SLOT(insertChildNode(QString, QString)));
 | 
		
	
		
			
			| 15161 | 15168 |  	addAnnotationControlButton->setMenu(annotationMenu);
 | 
		
	
		
			
			| 15162 | 15169 |  	layout->addWidget(addAnnotationControlButton);
 | 
		
	
		
			
			| 15163 | 15170 |  	QPushButton *advancedButton = new QPushButton(tr("Advanced Features"));
 | 
		
	
	
		
			
			|  | @@ -15190,7 +15197,7 @@ RoasterConfWidget::RoasterConfWidget(DeviceTreeModel *model, const QModelIndex &
 | 
		
	
		
			
			| 15190 | 15197 |  	connect(id, SIGNAL(valueChanged(int)), this, SLOT(updateRoasterId(int)));
 | 
		
	
		
			
			| 15191 | 15198 |  	setLayout(layout);
 | 
		
	
		
			
			| 15192 | 15199 |  }
 | 
		
	
		
			
			| 15193 |  | -	
 | 
		
	
		
			
			|  | 15200 | +
 | 
		
	
		
			
			| 15194 | 15201 |  @ Iterating over the configuration data associated with the current node is
 | 
		
	
		
			
			| 15195 | 15202 |  required in nearly every configuration widget. The specifics of the loop
 | 
		
	
		
			
			| 15196 | 15203 |  vary, but there is likely a better way to generalize that. Until then,
 | 
		
	
	
		
			
			|  | @@ -15452,7 +15459,7 @@ app.registerDeviceConfigurationWidget("nidaqmxbase9211series",
 | 
		
	
		
			
			| 15452 | 15459 |  	NiDaqMxBase9211ConfWidget::staticMetaObject);
 | 
		
	
		
			
			| 15453 | 15460 |  app.registerDeviceConfigurationWidget("ni9211seriestc",
 | 
		
	
		
			
			| 15454 | 15461 |  	Ni9211TcConfWidget::staticMetaObject);
 | 
		
	
		
			
			| 15455 |  | -	
 | 
		
	
		
			
			|  | 15462 | +
 | 
		
	
		
			
			| 15456 | 15463 |  @ Furthermore, we should create the NodeInserter objects for adding top level
 | 
		
	
		
			
			| 15457 | 15464 |  nodes to the configuration. Preferably we would only allow top level nodes to
 | 
		
	
		
			
			| 15458 | 15465 |  be inserted when all prerequisite software is available.
 | 
		
	
	
		
			
			|  | @@ -16639,7 +16646,7 @@ inserter = new NodeInserter(tr("Modbus RTU Port"), tr("Modbus RTU Port"), "modbu
 | 
		
	
		
			
			| 16639 | 16646 |  topLevelNodeInserters.append(inserter);
 | 
		
	
		
			
			| 16640 | 16647 |  #endif
 | 
		
	
		
			
			| 16641 | 16648 |  
 | 
		
	
		
			
			| 16642 |  | -@* Configuration of Annotation Controls.
 | 
		
	
		
			
			|  | 16649 | +@** Configuration of Annotation Controls.
 | 
		
	
		
			
			| 16643 | 16650 |  
 | 
		
	
		
			
			| 16644 | 16651 |  \noindent Aside from the details of hardware devices, the logging view must
 | 
		
	
		
			
			| 16645 | 16652 |  also be able to set up log annotation controls. A few different control types
 | 
		
	
	
		
			
			|  | @@ -16908,6 +16915,8 @@ void NoteSpinConfWidget::updatePosttext(const QString &text)
 | 
		
	
		
			
			| 16908 | 16915 |  @<Register device configuration widgets@>=
 | 
		
	
		
			
			| 16909 | 16916 |  app.registerDeviceConfigurationWidget("annotationspinbox", NoteSpinConfWidget::staticMetaObject);
 | 
		
	
		
			
			| 16910 | 16917 |  
 | 
		
	
		
			
			|  | 16918 | +@i freeannotation.w
 | 
		
	
		
			
			|  | 16919 | +
 | 
		
	
		
			
			| 16911 | 16920 |  @** Communicating with a Device through Modbus RTU.
 | 
		
	
		
			
			| 16912 | 16921 |  
 | 
		
	
		
			
			| 16913 | 16922 |  \noindent The classes described here need to be further generalized to support
 | 
		
	
	
		
			
			|  | @@ -17362,7 +17371,7 @@ Messages with a function number of 0x03 or 0x04 will be at least 7 bytes in
 | 
		
	
		
			
			| 17362 | 17371 |  length with the total length determined by the sum of 5 and the value in the
 | 
		
	
		
			
			| 17363 | 17372 |  fifth byte. Messages with a function number of 0x05, 0x06, or 0x10 will be 8
 | 
		
	
		
			
			| 17364 | 17373 |  bytes in length. Messages with a function number greater than 0x80 will be five
 | 
		
	
		
			
			| 17365 |  | -bytes in length. 
 | 
		
	
		
			
			|  | 17374 | +bytes in length.
 | 
		
	
		
			
			| 17366 | 17375 |  
 | 
		
	
		
			
			| 17367 | 17376 |  @<Check Modbus RTU message size@>=
 | 
		
	
		
			
			| 17368 | 17377 |  if(responseBuffer.size() < 5)
 | 
		
	
	
		
			
			|  | @@ -17480,7 +17489,7 @@ void ModbusRTUDevice::outputSV(double value)
 | 
		
	
		
			
			| 17480 | 17489 |  	char *valBytes = (char*)&outval;
 | 
		
	
		
			
			| 17481 | 17490 |  	message.append(valBytes[1]);
 | 
		
	
		
			
			| 17482 | 17491 |  	message.append(valBytes[0]);
 | 
		
	
		
			
			| 17483 |  | -	queueMessage(message, this, "ignore(QByteArray)");	
 | 
		
	
		
			
			|  | 17492 | +	queueMessage(message, this, "ignore(QByteArray)");
 | 
		
	
		
			
			| 17484 | 17493 |  }
 | 
		
	
		
			
			| 17485 | 17494 |  
 | 
		
	
		
			
			| 17486 | 17495 |  @ We don't care about the response when sending a new SV.
 | 
		
	
	
		
			
			|  | @@ -18144,7 +18153,7 @@ LinearSplineInterpolationConfWidget::LinearSplineInterpolationConfWidget(DeviceT
 | 
		
	
		
			
			| 18144 | 18153 |  			@<Convert numeric array literal to list@>@;
 | 
		
	
		
			
			| 18145 | 18154 |  			int column = 0;
 | 
		
	
		
			
			| 18146 | 18155 |  			@<Populate model column from list@>@;
 | 
		
	
		
			
			| 18147 |  | -			
 | 
		
	
		
			
			|  | 18156 | +
 | 
		
	
		
			
			| 18148 | 18157 |  		}
 | 
		
	
		
			
			| 18149 | 18158 |  		else if(node.attribute("name") == "destinationvalues")
 | 
		
	
		
			
			| 18150 | 18159 |  		{
 | 
		
	
	
		
			
			|  | @@ -18183,7 +18192,7 @@ for(int i = 0; i < itemList.size(); i++)
 | 
		
	
		
			
			| 18183 | 18192 |  {
 | 
		
	
		
			
			| 18184 | 18193 |  	knotmodel->setData(knotmodel->index(i, column),
 | 
		
	
		
			
			| 18185 | 18194 |  	                   QVariant(itemList.at(i).toDouble()),
 | 
		
	
		
			
			| 18186 |  | -                       Qt::DisplayRole);   
 | 
		
	
		
			
			|  | 18195 | +                       Qt::DisplayRole);
 | 
		
	
		
			
			| 18187 | 18196 |  }
 | 
		
	
		
			
			| 18188 | 18197 |  
 | 
		
	
		
			
			| 18189 | 18198 |  @ When data in the table is changed we simply overwrite any previously saved
 |