| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the documentation of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:FDL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Free Documentation License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Free |
| ** Documentation License version 1.3 as published by the Free Software |
| ** Foundation and appearing in the file included in the packaging of |
| ** this file. Please review the following information to ensure |
| ** the GNU Free Documentation License version 1.3 requirements |
| ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| /*! |
| \example widgets/calculator |
| \title Calculator Example |
| \ingroup examples-widgets |
| \ingroup examples-layout |
| \brief The example shows how to use signals and slots to implement the |
| functionality of a calculator widget, and how to use QGridLayout |
| to place child widgets in a grid. |
| |
| \borderedimage calculator-example.png |
| \caption Screenshot of the Calculator example |
| |
| The example consists of two classes: |
| |
| \list |
| \li \c Calculator is the calculator widget, with all the |
| calculator functionality. |
| \li \c Button is the widget used for each of the calculator |
| button. It derives from QToolButton. |
| \endlist |
| |
| We will start by reviewing \c Calculator, then we will take a |
| look at \c Button. |
| |
| \section1 Calculator Class Definition |
| |
| \snippet widgets/calculator/calculator.h 0 |
| |
| The \c Calculator class provides a simple calculator widget. It |
| inherits from QDialog and has several private slots associated |
| with the calculator's buttons. QObject::eventFilter() is |
| reimplemented to handle mouse events on the calculator's display. |
| |
| Buttons are grouped in categories according to their behavior. |
| For example, all the digit buttons (labeled \uicontrol 0 to \uicontrol 9) |
| append a digit to the current operand. For these, we connect |
| multiple buttons to the same slot (e.g., \c digitClicked()). The |
| categories are digits, unary operators (\uicontrol{Sqrt}, \uicontrol{x\unicode{178}}, |
| \uicontrol{1/x}), additive operators (\uicontrol{+}, \uicontrol{-}), and |
| multiplicative operators (\uicontrol{\unicode{215}}, \uicontrol{\unicode{247}}). The other buttons |
| have their own slots. |
| |
| \snippet widgets/calculator/calculator.h 1 |
| \snippet widgets/calculator/calculator.h 2 |
| |
| The private \c createButton() function is used as part of the |
| widget construction. \c abortOperation() is called whenever a |
| division by zero occurs or when a square root operation is |
| applied to a negative number. \c calculate() applies a binary |
| operator (\uicontrol{+}, \uicontrol{-}, \uicontrol{\unicode{215}}, or \uicontrol{\unicode{247}}). |
| |
| \snippet widgets/calculator/calculator.h 3 |
| \snippet widgets/calculator/calculator.h 4 |
| \snippet widgets/calculator/calculator.h 5 |
| \snippet widgets/calculator/calculator.h 6 |
| \snippet widgets/calculator/calculator.h 7 |
| \snippet widgets/calculator/calculator.h 8 |
| |
| These variables, together with the contents of the calculator |
| display (a QLineEdit), encode the state of the calculator: |
| |
| \list |
| \li \c sumInMemory contains the value stored in the calculator's memory |
| (using \uicontrol{MS}, \uicontrol{M+}, or \uicontrol{MC}). |
| \li \c sumSoFar stores the value accumulated so far. When the user |
| clicks \uicontrol{=}, \c sumSoFar is recomputed and shown on the |
| display. \uicontrol{Clear All} resets \c sumSoFar to zero. |
| \li \c factorSoFar stores a temporary value when doing |
| multiplications and divisions. |
| \li \c pendingAdditiveOperator stores the last additive operator |
| clicked by the user. |
| \li \c pendingMultiplicativeOperator stores the last multiplicative operator |
| clicked by the user. |
| \li \c waitingForOperand is \c true when the calculator is |
| expecting the user to start typing an operand. |
| \endlist |
| |
| Additive and multiplicative operators are treated differently |
| because they have different precedences. For example, \uicontrol{1 + 2 \unicode{247} |
| 3} is interpreted as \uicontrol{1 + (2 \unicode{247} 3)} because \uicontrol{\unicode{247}} has higher |
| precedence than \uicontrol{+}. |
| |
| The table below shows the evolution of the calculator state as |
| the user enters a mathematical expression. |
| |
| \table |
| \header \li User Input \li Display \li Sum so Far \li Add. Op. \li Factor so Far \li Mult. Op. \li Waiting for Operand? |
| \row \li \li 0 \li 0 \li \li \li \li \c true |
| \row \li \uicontrol{1} \li 1 \li 0 \li \li \li \li \c false |
| \row \li \uicontrol{1 +} \li 1 \li 1 \li \uicontrol{+} \li \li \li \c true |
| \row \li \uicontrol{1 + 2} \li 2 \li 1 \li \uicontrol{+} \li \li \li \c false |
| \row \li \uicontrol{1 + 2 \unicode{247}} \li 2 \li 1 \li \uicontrol{+} \li 2 \li \uicontrol{\unicode{247}} \li \c true |
| \row \li \uicontrol{1 + 2 \unicode{247} 3} \li 3 \li 1 \li \uicontrol{+} \li 2 \li \uicontrol{\unicode{247}} \li \c false |
| \row \li \uicontrol{1 + 2 \unicode{247} 3 -} \li 1.66667 \li 1.66667 \li \uicontrol{-} \li \li \li \c true |
| \row \li \uicontrol{1 + 2 \unicode{247} 3 - 4} \li 4 \li 1.66667 \li \uicontrol{-} \li \li \li \c false |
| \row \li \uicontrol{1 + 2 \unicode{247} 3 - 4 =} \li -2.33333 \li 0 \li \li \li \li \c true |
| \endtable |
| |
| Unary operators, such as \uicontrol Sqrt, require no special handling; |
| they can be applied immediately since the operand is already |
| known when the operator button is clicked. |
| |
| \snippet widgets/calculator/calculator.h 9 |
| \codeline |
| \snippet widgets/calculator/calculator.h 10 |
| |
| Finally, we declare the variables associated with the display and the |
| buttons used to display numerals. |
| |
| \section1 Calculator Class Implementation |
| |
| \snippet widgets/calculator/calculator.cpp 0 |
| |
| In the constructor, we initialize the calculator's state. The \c |
| pendingAdditiveOperator and \c pendingMultiplicativeOperator |
| variables don't need to be initialized explicitly, because the |
| QString constructor initializes them to empty strings. |
| It is also possible to initialize those variable directly in the |
| header. This is called \c member-initializaton and avoids a long |
| initialization list. |
| |
| \snippet widgets/calculator/calculator.cpp 1 |
| \snippet widgets/calculator/calculator.cpp 2 |
| |
| We create the QLineEdit representing the calculator's display and |
| set up some of its properties. In particular, we set it to be |
| read-only. |
| |
| We also enlarge \c{display}'s font by 8 points. |
| |
| \snippet widgets/calculator/calculator.cpp 4 |
| |
| For each button, we call the private \c createButton() function with |
| the proper text label and a slot to connect to the button. |
| |
| \snippet widgets/calculator/calculator.cpp 5 |
| \snippet widgets/calculator/calculator.cpp 6 |
| |
| The layout is handled by a single QGridLayout. The |
| QLayout::setSizeConstraint() call ensures that the \c Calculator |
| widget is always shown as its optimal size (its |
| \l{QWidget::sizeHint()}{size hint}), preventing the user from |
| resizing the calculator. The size hint is determined by the size |
| and \l{QWidget::sizePolicy()}{size policy} of the child widgets. |
| |
| Most child widgets occupy only one cell in the grid layout. For |
| these, we only need to pass a row and a column to |
| QGridLayout::addWidget(). The \c display, \c backspaceButton, \c |
| clearButton, and \c clearAllButton widgets occupy more than one |
| column; for these we must also pass a row span and a column |
| span. |
| |
| \snippet widgets/calculator/calculator.cpp 7 |
| |
| Pressing one of the calculator's digit buttons will emit the |
| button's \l{QToolButton::clicked()}{clicked()} signal, which will |
| trigger the \c digitClicked() slot. |
| |
| First, we find out which button sent the signal using |
| QObject::sender(). This function returns the sender as a QObject |
| pointer. Since we know that the sender is a \c Button object, we |
| can safely cast the QObject. We could have used a C-style cast or |
| a C++ \c static_cast<>(), but as a defensive programming |
| technique we use a \l qobject_cast(). The advantage is that if |
| the object has the wrong type, a null pointer is returned. |
| Crashes due to null pointers are much easier to diagnose than |
| crashes due to unsafe casts. Once we have the button, we extract |
| the operator using QToolButton::text(). |
| |
| The slot needs to consider two situations in particular. If \c |
| display contains "0" and the user clicks the \uicontrol{0} button, it |
| would be silly to show "00". And if the calculator is in |
| a state where it is waiting for a new operand, |
| the new digit is the first digit of that new operand; in that case, |
| any result of a previous calculation must be cleared first. |
| |
| At the end, we append the new digit to the value in the display. |
| |
| \snippet widgets/calculator/calculator.cpp 8 |
| \snippet widgets/calculator/calculator.cpp 9 |
| |
| The \c unaryOperatorClicked() slot is called whenever one of the |
| unary operator buttons is clicked. Again a pointer to the clicked |
| button is retrieved using QObject::sender(). The operator is |
| extracted from the button's text and stored in \c |
| clickedOperator. The operand is obtained from \c display. |
| |
| Then we perform the operation. If \uicontrol Sqrt is applied to a |
| negative number or \uicontrol{1/x} to zero, we call \c |
| abortOperation(). If everything goes well, we display the result |
| of the operation in the line edit and we set \c waitingForOperand |
| to \c true. This ensures that if the user types a new digit, the |
| digit will be considered as a new operand, instead of being |
| appended to the current value. |
| |
| \snippet widgets/calculator/calculator.cpp 10 |
| \snippet widgets/calculator/calculator.cpp 11 |
| |
| The \c additiveOperatorClicked() slot is called when the user |
| clicks the \uicontrol{+} or \uicontrol{-} button. |
| |
| Before we can actually do something about the clicked operator, |
| we must handle any pending operations. We start with the |
| multiplicative operators, since these have higher precedence than |
| additive operators: |
| |
| \snippet widgets/calculator/calculator.cpp 12 |
| \snippet widgets/calculator/calculator.cpp 13 |
| |
| If \uicontrol{\unicode{215}} or \uicontrol{\unicode{247}} has been clicked earlier, without clicking |
| \uicontrol{=} afterward, the current value in the display is the right |
| operand of the \uicontrol{\unicode{215}} or \uicontrol{\unicode{247}} operator and we can finally |
| perform the operation and update the display. |
| |
| \snippet widgets/calculator/calculator.cpp 14 |
| \snippet widgets/calculator/calculator.cpp 15 |
| |
| If \uicontrol{+} or \uicontrol{-} has been clicked earlier, \c sumSoFar is |
| the left operand and the current value in the display is the |
| right operand of the operator. If there is no pending additive |
| operator, \c sumSoFar is simply set to be the text in the |
| display. |
| |
| \snippet widgets/calculator/calculator.cpp 16 |
| \snippet widgets/calculator/calculator.cpp 17 |
| |
| Finally, we can take care of the operator that was just clicked. |
| Since we don't have the right-hand operand yet, we store the clicked |
| operator in the \c pendingAdditiveOperator variable. We will |
| apply the operation later, when we have a right operand, with \c |
| sumSoFar as the left operand. |
| |
| \snippet widgets/calculator/calculator.cpp 18 |
| |
| The \c multiplicativeOperatorClicked() slot is similar to \c |
| additiveOperatorClicked(). We don't need to worry about pending |
| additive operators here, because multiplicative operators have |
| precedence over additive operators. |
| |
| \snippet widgets/calculator/calculator.cpp 20 |
| |
| Like in \c additiveOperatorClicked(), we start by handling any |
| pending multiplicative and additive operators. Then we display \c |
| sumSoFar and reset the variable to zero. Resetting the variable |
| to zero is necessary to avoid counting the value twice. |
| |
| \snippet widgets/calculator/calculator.cpp 22 |
| |
| The \c pointClicked() slot adds a decimal point to the content in |
| \c display. |
| |
| \snippet widgets/calculator/calculator.cpp 24 |
| |
| The \c changeSignClicked() slot changes the sign of the value in |
| \c display. If the current value is positive, we prepend a minus |
| sign; if the current value is negative, we remove the first |
| character from the value (the minus sign). |
| |
| \snippet widgets/calculator/calculator.cpp 26 |
| |
| The \c backspaceClicked() removes the rightmost character in the |
| display. If we get an empty string, we show "0" and set \c |
| waitingForOperand to \c true. |
| |
| \snippet widgets/calculator/calculator.cpp 28 |
| |
| The \c clear() slot resets the current operand to zero. It is |
| equivalent to clicking \uicontrol Backspace enough times to erase the |
| entire operand. |
| |
| \snippet widgets/calculator/calculator.cpp 30 |
| |
| The \c clearAll() slot resets the calculator to its initial state. |
| |
| \snippet widgets/calculator/calculator.cpp 32 |
| |
| The \c clearMemory() slot erases the sum kept in memory, \c |
| readMemory() displays the sum as an operand, \c setMemory() |
| replace the sum in memory with the current sum, and \c |
| addToMemory() adds the current value to the value in memory. For |
| \c setMemory() and \c addToMemory(), we start by calling \c |
| equalClicked() to update \c sumSoFar and the value in the |
| display. |
| |
| \snippet widgets/calculator/calculator.cpp 34 |
| |
| The private \c createButton() function is called from the |
| constructor to create calculator buttons. |
| |
| \snippet widgets/calculator/calculator.cpp 36 |
| |
| The private \c abortOperation() function is called whenever a |
| calculation fails. It resets the calculator state and displays |
| "####". |
| |
| \snippet widgets/calculator/calculator.cpp 38 |
| |
| The private \c calculate() function performs a binary operation. |
| The right operand is given by \c rightOperand. For additive |
| operators, the left operand is \c sumSoFar; for multiplicative |
| operators, the left operand is \c factorSoFar. The function |
| return \c false if a division by zero occurs. |
| |
| \section1 Button Class Definition |
| |
| Let's now take a look at the \c Button class: |
| |
| \snippet widgets/calculator/button.h 0 |
| |
| The \c Button class has a convenience constructor that takes a |
| text label and a parent widget, and it reimplements QWidget::sizeHint() |
| to provide more space around the text than the amount QToolButton |
| normally provides. |
| |
| \section1 Button Class Implementation |
| |
| \snippet widgets/calculator/button.cpp 0 |
| |
| The buttons' appearance is determined by the layout of the |
| calculator widget through the size and |
| \l{QWidget::sizePolicy}{size policy} of the layout's child |
| widgets. The call to the |
| \l{QWidget::setSizePolicy()}{setSizePolicy()} function in the |
| constructor ensures that the button will expand horizontally to |
| fill all the available space; by default, \l{QToolButton}s don't |
| expand to fill available space. Without this call, the different |
| buttons in a same column would have different widths. |
| |
| \snippet widgets/calculator/button.cpp 1 |
| \snippet widgets/calculator/button.cpp 2 |
| |
| In \l{QWidget::sizeHint()}{sizeHint()}, we try to return a size |
| that looks good for most buttons. We reuse the size hint of the |
| base class (QToolButton) but modify it in the following ways: |
| |
| \list |
| \li We add 20 to the \l{QSize::height()}{height} component of the size hint. |
| \li We make the \l{QSize::width()}{width} component of the size |
| hint at least as much as the \l{QSize::width()}{height}. |
| \endlist |
| |
| This ensures that with most fonts, the digit and operator buttons |
| will be square, without truncating the text on the |
| \uicontrol{Backspace}, \uicontrol{Clear}, and \uicontrol{Clear All} buttons. |
| |
| The screenshot below shows how the \c Calculator widget would |
| look like if we \e didn't set the horizontal size policy to |
| QSizePolicy::Expanding in the constructor and if we didn't |
| reimplement QWidget::sizeHint(). |
| |
| \borderedimage calculator-ugly.png |
| \caption The Calculator example with default size policies and size hints |
| |
| */ |