doc/src/examples/calculator.qdoc
changeset 0 1918ee327afb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/examples/calculator.qdoc	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,389 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+    \example widgets/calculator
+    \title Calculator Example
+
+    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.
+
+    \image calculator-example.png Screenshot of the Calculator example
+
+    The example consists of two classes:
+
+    \list
+    \o \c Calculator is the calculator widget, with all the
+       calculator functionality.
+    \o \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 examples/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 \gui 0 to \gui 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 (\gui{Sqrt}, \gui{x\unicode{178}},
+    \gui{1/x}), additive operators (\gui{+}, \gui{-}), and
+    multiplicative operators (\gui{\unicode{215}}, \gui{\unicode{247}}). The other buttons
+    have their own slots.
+
+    \snippet examples/widgets/calculator/calculator.h 1
+    \snippet examples/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 (\gui{+}, \gui{-}, \gui{\unicode{215}}, or \gui{\unicode{247}}).
+
+    \snippet examples/widgets/calculator/calculator.h 3
+    \snippet examples/widgets/calculator/calculator.h 4
+    \snippet examples/widgets/calculator/calculator.h 5
+    \snippet examples/widgets/calculator/calculator.h 6
+    \snippet examples/widgets/calculator/calculator.h 7
+    \snippet examples/widgets/calculator/calculator.h 8
+
+    These variables, together with the contents of the calculator
+    display (a QLineEdit), encode the state of the calculator:
+
+    \list
+    \o \c sumInMemory contains the value stored in the calculator's memory
+       (using \gui{MS}, \gui{M+}, or \gui{MC}).
+    \o \c sumSoFar stores the value accumulated so far. When the user
+       clicks \gui{=}, \c sumSoFar is recomputed and shown on the
+       display. \gui{Clear All} resets \c sumSoFar to zero.
+    \o \c factorSoFar stores a temporary value when doing
+        multiplications and divisions.
+    \o \c pendingAdditiveOperator stores the last additive operator
+       clicked by the user.
+    \o \c pendingMultiplicativeOperator stores the last multiplicative operator
+       clicked by the user.
+    \o \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, \gui{1 + 2 \unicode{247}
+    3} is interpreted as \gui{1 + (2 \unicode{247} 3)} because \gui{\unicode{247}} has higher
+    precedence than \gui{+}.
+
+    The table below shows the evolution of the calculator state as
+    the user enters a mathematical expression.
+
+    \table
+    \header \o User Input            \o Display  \o Sum so Far \o Add. Op. \o Factor so Far \o Mult. Op. \o Waiting for Operand?
+    \row    \o                       \o 0        \o 0          \o          \o               \o           \o \c true
+    \row    \o \gui{1}               \o 1        \o 0          \o          \o               \o           \o \c false
+    \row    \o \gui{1 +}             \o 1        \o 1          \o \gui{+}  \o               \o           \o \c true
+    \row    \o \gui{1 + 2}           \o 2        \o 1          \o \gui{+}  \o               \o           \o \c false
+    \row    \o \gui{1 + 2 \unicode{247}}         \o 2        \o 1          \o \gui{+}  \o 2             \o \gui{\unicode{247}}   \o \c true
+    \row    \o \gui{1 + 2 \unicode{247} 3}       \o 3        \o 1          \o \gui{+}  \o 2             \o \gui{\unicode{247}}   \o \c false
+    \row    \o \gui{1 + 2 \unicode{247} 3 -}     \o 1.66667  \o 1.66667    \o \gui{-}  \o               \o           \o \c true
+    \row    \o \gui{1 + 2 \unicode{247} 3 - 4}   \o 4        \o 1.66667    \o \gui{-}  \o               \o           \o \c false
+    \row    \o \gui{1 + 2 \unicode{247} 3 - 4 =} \o -2.33333 \o 0          \o          \o               \o           \o \c true
+    \endtable
+
+    Unary operators, such as \gui Sqrt, require no special handling;
+    they can be applied immediately since the operand is already
+    known when the operator button is clicked.
+
+    \snippet examples/widgets/calculator/calculator.h 9
+    \codeline
+    \snippet examples/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 examples/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.
+
+    \snippet examples/widgets/calculator/calculator.cpp 1
+    \snippet examples/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 examples/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 examples/widgets/calculator/calculator.cpp 5
+    \snippet examples/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 examples/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 \gui{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 examples/widgets/calculator/calculator.cpp 8
+    \snippet examples/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 \gui Sqrt is applied to a
+    negative number or \gui{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 examples/widgets/calculator/calculator.cpp 10
+    \snippet examples/widgets/calculator/calculator.cpp 11
+
+    The \c additiveOperatorClicked() slot is called when the user
+    clicks the \gui{+} or \gui{-} 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 examples/widgets/calculator/calculator.cpp 12
+    \snippet examples/widgets/calculator/calculator.cpp 13
+
+    If \gui{\unicode{215}} or \gui{\unicode{247}} has been clicked earlier, without clicking
+    \gui{=} afterward, the current value in the display is the right
+    operand of the \gui{\unicode{215}} or \gui{\unicode{247}} operator and we can finally
+    perform the operation and update the display.
+
+    \snippet examples/widgets/calculator/calculator.cpp 14
+    \snippet examples/widgets/calculator/calculator.cpp 15
+
+    If \gui{+} or \gui{-} 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 examples/widgets/calculator/calculator.cpp 16
+    \snippet examples/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 examples/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 examples/widgets/calculator/calculator.cpp 20
+
+    Like in \c additiveOperatorClicked(), we start by handing 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 examples/widgets/calculator/calculator.cpp 22
+
+    The \c pointClicked() slot adds a decimal point to the content in
+    \c display.
+
+    \snippet examples/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 examples/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 examples/widgets/calculator/calculator.cpp 28
+
+    The \c clear() slot resets the current operand to zero. It is
+    equivalent to clicking \gui Backspace enough times to erase the
+    entire operand.
+
+    \snippet examples/widgets/calculator/calculator.cpp 30
+
+    The \c clearAll() slot resets the calculator to its initial state.
+
+    \snippet examples/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 examples/widgets/calculator/calculator.cpp 34
+
+    The private \c createButton() function is called from the
+    constructor to create calculator buttons.
+
+    \snippet examples/widgets/calculator/calculator.cpp 36
+
+    The private \c abortOperation() function is called whenever a
+    calculation fails. It resets the calculator state and displays
+    "####".
+
+    \snippet examples/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 examples/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 examples/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 examples/widgets/calculator/button.cpp 1
+    \snippet examples/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
+    \o We add 20 to the \l{QSize::height()}{height} component of the size hint.
+    \o 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
+    \gui{Backspace}, \gui{Clear}, and \gui{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().
+
+    \image calculator-ugly.png The Calculator example with default size policies and size hints
+
+*/