I don't think this was intentional...
[qt-netbsd.git] / doc / src / examples / calculator.qdoc
blob306f97269ec6ca2eacf93c52fabacc2b89cf1dd5
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the documentation of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
38 ** $QT_END_LICENSE$
40 ****************************************************************************/
42 /*!
43     \example widgets/calculator
44     \title Calculator Example
46     The example shows how to use signals and slots to implement the
47     functionality of a calculator widget, and how to use QGridLayout
48     to place child widgets in a grid.
50     \image calculator-example.png Screenshot of the Calculator example
52     The example consists of two classes:
54     \list
55     \o \c Calculator is the calculator widget, with all the
56        calculator functionality.
57     \o \c Button is the widget used for each of the calculator
58        button. It derives from QToolButton.
59     \endlist
61     We will start by reviewing \c Calculator, then we will take a
62     look at \c Button.
64     \section1 Calculator Class Definition
66     \snippet examples/widgets/calculator/calculator.h 0
68     The \c Calculator class provides a simple calculator widget. It
69     inherits from QDialog and has several private slots associated
70     with the calculator's buttons. QObject::eventFilter() is
71     reimplemented to handle mouse events on the calculator's display.
73     Buttons are grouped in categories according to their behavior.
74     For example, all the digit buttons (labeled \gui 0 to \gui 9)
75     append a digit to the current operand. For these, we connect
76     multiple buttons to the same slot (e.g., \c digitClicked()). The
77     categories are digits, unary operators (\gui{Sqrt}, \gui{x\unicode{178}},
78     \gui{1/x}), additive operators (\gui{+}, \gui{-}), and
79     multiplicative operators (\gui{\unicode{215}}, \gui{\unicode{247}}). The other buttons
80     have their own slots.
82     \snippet examples/widgets/calculator/calculator.h 1
83     \snippet examples/widgets/calculator/calculator.h 2
85     The private \c createButton() function is used as part of the
86     widget construction. \c abortOperation() is called whenever a
87     division by zero occurs or when a square root operation is
88     applied to a negative number. \c calculate() applies a binary
89     operator (\gui{+}, \gui{-}, \gui{\unicode{215}}, or \gui{\unicode{247}}).
91     \snippet examples/widgets/calculator/calculator.h 3
92     \snippet examples/widgets/calculator/calculator.h 4
93     \snippet examples/widgets/calculator/calculator.h 5
94     \snippet examples/widgets/calculator/calculator.h 6
95     \snippet examples/widgets/calculator/calculator.h 7
96     \snippet examples/widgets/calculator/calculator.h 8
98     These variables, together with the contents of the calculator
99     display (a QLineEdit), encode the state of the calculator:
101     \list
102     \o \c sumInMemory contains the value stored in the calculator's memory
103        (using \gui{MS}, \gui{M+}, or \gui{MC}).
104     \o \c sumSoFar stores the value accumulated so far. When the user
105        clicks \gui{=}, \c sumSoFar is recomputed and shown on the
106        display. \gui{Clear All} resets \c sumSoFar to zero.
107     \o \c factorSoFar stores a temporary value when doing
108         multiplications and divisions.
109     \o \c pendingAdditiveOperator stores the last additive operator
110        clicked by the user.
111     \o \c pendingMultiplicativeOperator stores the last multiplicative operator
112        clicked by the user.
113     \o \c waitingForOperand is \c true when the calculator is
114        expecting the user to start typing an operand.
115     \endlist
117     Additive and multiplicative operators are treated differently
118     because they have different precedences. For example, \gui{1 + 2 \unicode{247}
119     3} is interpreted as \gui{1 + (2 \unicode{247} 3)} because \gui{\unicode{247}} has higher
120     precedence than \gui{+}.
122     The table below shows the evolution of the calculator state as
123     the user enters a mathematical expression.
125     \table
126     \header \o User Input            \o Display  \o Sum so Far \o Add. Op. \o Factor so Far \o Mult. Op. \o Waiting for Operand?
127     \row    \o                       \o 0        \o 0          \o          \o               \o           \o \c true
128     \row    \o \gui{1}               \o 1        \o 0          \o          \o               \o           \o \c false
129     \row    \o \gui{1 +}             \o 1        \o 1          \o \gui{+}  \o               \o           \o \c true
130     \row    \o \gui{1 + 2}           \o 2        \o 1          \o \gui{+}  \o               \o           \o \c false
131     \row    \o \gui{1 + 2 \unicode{247}}         \o 2        \o 1          \o \gui{+}  \o 2             \o \gui{\unicode{247}}   \o \c true
132     \row    \o \gui{1 + 2 \unicode{247} 3}       \o 3        \o 1          \o \gui{+}  \o 2             \o \gui{\unicode{247}}   \o \c false
133     \row    \o \gui{1 + 2 \unicode{247} 3 -}     \o 1.66667  \o 1.66667    \o \gui{-}  \o               \o           \o \c true
134     \row    \o \gui{1 + 2 \unicode{247} 3 - 4}   \o 4        \o 1.66667    \o \gui{-}  \o               \o           \o \c false
135     \row    \o \gui{1 + 2 \unicode{247} 3 - 4 =} \o -2.33333 \o 0          \o          \o               \o           \o \c true
136     \endtable
138     Unary operators, such as \gui Sqrt, require no special handling;
139     they can be applied immediately since the operand is already
140     known when the operator button is clicked.
142     \snippet examples/widgets/calculator/calculator.h 9
143     \codeline
144     \snippet examples/widgets/calculator/calculator.h 10
146     Finally, we declare the variables associated with the display and the
147     buttons used to display numerals.
149     \section1 Calculator Class Implementation
151     \snippet examples/widgets/calculator/calculator.cpp 0
153     In the constructor, we initialize the calculator's state. The \c
154     pendingAdditiveOperator and \c pendingMultiplicativeOperator
155     variables don't need to be initialized explicitly, because the
156     QString constructor initializes them to empty strings.
158     \snippet examples/widgets/calculator/calculator.cpp 1
159     \snippet examples/widgets/calculator/calculator.cpp 2
161     We create the QLineEdit representing the calculator's display and
162     set up some of its properties. In particular, we set it to be
163     read-only.
165     We also enlarge \c{display}'s font by 8 points.
167     \snippet examples/widgets/calculator/calculator.cpp 4
169     For each button, we call the private \c createButton() function with
170     the proper text label and a slot to connect to the button.
172     \snippet examples/widgets/calculator/calculator.cpp 5
173     \snippet examples/widgets/calculator/calculator.cpp 6
175     The layout is handled by a single QGridLayout. The
176     QLayout::setSizeConstraint() call ensures that the \c Calculator
177     widget is always shown as its optimal size (its
178     \l{QWidget::sizeHint()}{size hint}), preventing the user from
179     resizing the calculator. The size hint is determined by the size
180     and \l{QWidget::sizePolicy()}{size policy} of the child widgets.
182     Most child widgets occupy only one cell in the grid layout. For
183     these, we only need to pass a row and a column to
184     QGridLayout::addWidget(). The \c display, \c backspaceButton, \c
185     clearButton, and \c clearAllButton widgets occupy more than one
186     column; for these we must also pass a row span and a column
187     span.
189     \snippet examples/widgets/calculator/calculator.cpp 7
191     Pressing one of the calculator's digit buttons will emit the
192     button's \l{QToolButton::clicked()}{clicked()} signal, which will
193     trigger the \c digitClicked() slot.
195     First, we find out which button sent the signal using
196     QObject::sender(). This function returns the sender as a QObject
197     pointer. Since we know that the sender is a \c Button object, we
198     can safely cast the QObject. We could have used a C-style cast or
199     a C++ \c static_cast<>(), but as a defensive programming
200     technique we use a \l qobject_cast(). The advantage is that if
201     the object has the wrong type, a null pointer is returned.
202     Crashes due to null pointers are much easier to diagnose than
203     crashes due to unsafe casts. Once we have the button, we extract
204     the operator using QToolButton::text().
206     The slot needs to consider two situations in particular. If \c
207     display contains "0" and the user clicks the \gui{0} button, it
208     would be silly to show "00". And if the calculator is in
209     a state where it is waiting for a new operand,
210     the new digit is the first digit of that new operand; in that case,
211     any result of a previous calculation must be cleared first.
213     At the end, we append the new digit to the value in the display.
215     \snippet examples/widgets/calculator/calculator.cpp 8
216     \snippet examples/widgets/calculator/calculator.cpp 9
218     The \c unaryOperatorClicked() slot is called whenever one of the
219     unary operator buttons is clicked. Again a pointer to the clicked
220     button is retrieved using QObject::sender(). The operator is
221     extracted from the button's text and stored in \c
222     clickedOperator. The operand is obtained from \c display.
224     Then we perform the operation. If \gui Sqrt is applied to a
225     negative number or \gui{1/x} to zero, we call \c
226     abortOperation(). If everything goes well, we display the result
227     of the operation in the line edit and we set \c waitingForOperand
228     to \c true. This ensures that if the user types a new digit, the
229     digit will be considered as a new operand, instead of being
230     appended to the current value.
232     \snippet examples/widgets/calculator/calculator.cpp 10
233     \snippet examples/widgets/calculator/calculator.cpp 11
235     The \c additiveOperatorClicked() slot is called when the user
236     clicks the \gui{+} or \gui{-} button.
238     Before we can actually do something about the clicked operator,
239     we must handle any pending operations. We start with the
240     multiplicative operators, since these have higher precedence than
241     additive operators:
243     \snippet examples/widgets/calculator/calculator.cpp 12
244     \snippet examples/widgets/calculator/calculator.cpp 13
246     If \gui{\unicode{215}} or \gui{\unicode{247}} has been clicked earlier, without clicking
247     \gui{=} afterward, the current value in the display is the right
248     operand of the \gui{\unicode{215}} or \gui{\unicode{247}} operator and we can finally
249     perform the operation and update the display.
251     \snippet examples/widgets/calculator/calculator.cpp 14
252     \snippet examples/widgets/calculator/calculator.cpp 15
254     If \gui{+} or \gui{-} has been clicked earlier, \c sumSoFar is
255     the left operand and the current value in the display is the
256     right operand of the operator. If there is no pending additive
257     operator, \c sumSoFar is simply set to be the text in the
258     display.
260     \snippet examples/widgets/calculator/calculator.cpp 16
261     \snippet examples/widgets/calculator/calculator.cpp 17
263     Finally, we can take care of the operator that was just clicked.
264     Since we don't have the right-hand operand yet, we store the clicked
265     operator in the \c pendingAdditiveOperator variable. We will
266     apply the operation later, when we have a right operand, with \c
267     sumSoFar as the left operand.
269     \snippet examples/widgets/calculator/calculator.cpp 18
271     The \c multiplicativeOperatorClicked() slot is similar to \c
272     additiveOperatorClicked(). We don't need to worry about pending
273     additive operators here, because multiplicative operators have
274     precedence over additive operators.
276     \snippet examples/widgets/calculator/calculator.cpp 20
278     Like in \c additiveOperatorClicked(), we start by handing any
279     pending multiplicative and additive operators. Then we display \c
280     sumSoFar and reset the variable to zero. Resetting the variable
281     to zero is necessary to avoid counting the value twice.
283     \snippet examples/widgets/calculator/calculator.cpp 22
285     The \c pointClicked() slot adds a decimal point to the content in
286     \c display.
288     \snippet examples/widgets/calculator/calculator.cpp 24
290     The \c changeSignClicked() slot changes the sign of the value in
291     \c display. If the current value is positive, we prepend a minus
292     sign; if the current value is negative, we remove the first
293     character from the value (the minus sign).
295     \snippet examples/widgets/calculator/calculator.cpp 26
297     The \c backspaceClicked() removes the rightmost character in the
298     display. If we get an empty string, we show "0" and set \c
299     waitingForOperand to \c true.
301     \snippet examples/widgets/calculator/calculator.cpp 28
303     The \c clear() slot resets the current operand to zero. It is
304     equivalent to clicking \gui Backspace enough times to erase the
305     entire operand.
307     \snippet examples/widgets/calculator/calculator.cpp 30
309     The \c clearAll() slot resets the calculator to its initial state.
311     \snippet examples/widgets/calculator/calculator.cpp 32
313     The \c clearMemory() slot erases the sum kept in memory, \c
314     readMemory() displays the sum as an operand, \c setMemory()
315     replace the sum in memory with the current sum, and \c
316     addToMemory() adds the current value to the value in memory. For
317     \c setMemory() and \c addToMemory(), we start by calling \c
318     equalClicked() to update \c sumSoFar and the value in the
319     display.
321     \snippet examples/widgets/calculator/calculator.cpp 34
323     The private \c createButton() function is called from the
324     constructor to create calculator buttons.
326     \snippet examples/widgets/calculator/calculator.cpp 36
328     The private \c abortOperation() function is called whenever a
329     calculation fails. It resets the calculator state and displays
330     "####".
332     \snippet examples/widgets/calculator/calculator.cpp 38
334     The private \c calculate() function performs a binary operation.
335     The right operand is given by \c rightOperand. For additive
336     operators, the left operand is \c sumSoFar; for multiplicative
337     operators, the left operand is \c factorSoFar. The function
338     return \c false if a division by zero occurs.
340     \section1 Button Class Definition
342     Let's now take a look at the \c Button class:
344     \snippet examples/widgets/calculator/button.h 0
346     The \c Button class has a convenience constructor that takes a
347     text label and a parent widget, and it reimplements QWidget::sizeHint()
348     to provide more space around the text than the amount QToolButton
349     normally provides.
351     \section1 Button Class Implementation
353     \snippet examples/widgets/calculator/button.cpp 0
355     The buttons' appearance is determined by the layout of the
356     calculator widget through the size and
357     \l{QWidget::sizePolicy}{size policy} of the layout's child
358     widgets. The call to the
359     \l{QWidget::setSizePolicy()}{setSizePolicy()} function in the
360     constructor ensures that the button will expand horizontally to
361     fill all the available space; by default, \l{QToolButton}s don't
362     expand to fill available space. Without this call, the different
363     buttons in a same column would have different widths.
365     \snippet examples/widgets/calculator/button.cpp 1
366     \snippet examples/widgets/calculator/button.cpp 2
368     In \l{QWidget::sizeHint()}{sizeHint()}, we try to return a size
369     that looks good for most buttons. We reuse the size hint of the
370     base class (QToolButton) but modify it in the following ways:
372     \list
373     \o We add 20 to the \l{QSize::height()}{height} component of the size hint.
374     \o We make the \l{QSize::width()}{width} component of the size
375        hint at least as much as the \l{QSize::width()}{height}.
376     \endlist
378     This ensures that with most fonts, the digit and operator buttons
379     will be square, without truncating the text on the
380     \gui{Backspace}, \gui{Clear}, and \gui{Clear All} buttons.
382     The screenshot below shows how the \c Calculator widget would
383     look like if we \e didn't set the horizontal size policy to
384     QSizePolicy::Expanding in the constructor and if we didn't
385     reimplement QWidget::sizeHint().
387     \image calculator-ugly.png The Calculator example with default size policies and size hints