|  | Home · Examples

# QtScript Calculator Example

In this simple QtScript example, we show how to implement the functionality of a calculator widget.

The program logic in this example is a fairly straight port of the logic in the C++ Calculator Example. The graphical user interface is defined in a UI file.

The C++ part of the example consists of four steps:

- Evaluate the script code that defines the `Calculator` class.
  The following code example is written in c++.

          QScriptEngine engine;

          QFile scriptFile(":/calculator.js");
          scriptFile.open(QIODevice::ReadOnly);
          engine.evaluate(scriptFile.readAll());
          scriptFile.close();

- Create a widget from the UI file using QUiLoader.
  The following code example is written in c++.

          QUiLoader loader;
          QFile uiFile(":/calculator.ui");
          uiFile.open(QIODevice::ReadOnly);
          QWidget *ui = loader.load(&uiFile);
          uiFile.close();

- Call the Calculator constructor function to create a new `Calculator` script object, passing the widget as argument.
  The following code example is written in c++.

          QScriptValue ctor = engine.evaluate("Calculator");
          QScriptValue scriptUi = engine.newQObject(ui, QScriptEngine::ScriptOwnership);
          QScriptValue calc = ctor.construct(QScriptValueList() << scriptUi);

- Show the widget and start the application event loop.
  The following code example is written in c++.

          ui->show();
          return app.exec();

On the script side, the `Calculator` constructor function initializes the instance variables of the new `Calculator` object, and connects the clicked() signal of the form's buttons to corresponding functions defined in the `Calculator` prototype object; the effect is that when a button is clicked, the proper script function will be invoked to carry out the operation.

    function Calculator(ui)
    {
        this.ui = ui;

        this.pendingAdditiveOperator = "";
        this.pendingMultiplicativeOperator = "";
        this.sumInMemory = 0;
        this.sumSoFar = 0;
        this.factorSoFar = 0;
        this.waitingForOperand = true;

        with (ui) {
            display.text = "0";

            zeroButton.clicked.connect(this, this.digitClicked);
            oneButton.clicked.connect(this, "digitClicked");
            twoButton.clicked.connect(this, "digitClicked");
            threeButton.clicked.connect(this, "digitClicked");
            fourButton.clicked.connect(this, "digitClicked");
            fiveButton.clicked.connect(this, "digitClicked");
            sixButton.clicked.connect(this, "digitClicked");
            sevenButton.clicked.connect(this, "digitClicked");
            eightButton.clicked.connect(this, "digitClicked");
            nineButton.clicked.connect(this, "digitClicked");

            pointButton.clicked.connect(this, "pointClicked");
            changeSignButton.clicked.connect(this, "changeSignClicked");

            backspaceButton.clicked.connect(this, "backspaceClicked");
            clearButton.clicked.connect(this, "clear");
            clearAllButton.clicked.connect(this, "clearAll");

            clearMemoryButton.clicked.connect(this, "clearMemory");
            readMemoryButton.clicked.connect(this, "readMemory");
            setMemoryButton.clicked.connect(this, "setMemory");
            addToMemoryButton.clicked.connect(this, "addToMemory");

            divisionButton.clicked.connect(this, "multiplicativeOperatorClicked");
            timesButton.clicked.connect(this, "multiplicativeOperatorClicked");
            minusButton.clicked.connect(this, "additiveOperatorClicked");
            plusButton.clicked.connect(this, "additiveOperatorClicked");

            squareRootButton.clicked.connect(this, "unaryOperatorClicked");
            powerButton.clicked.connect(this, "unaryOperatorClicked");
            reciprocalButton.clicked.connect(this, "unaryOperatorClicked");
            equalButton.clicked.connect(this, "equalClicked");
        }
    }

A `Calculator` object is just a plain script object; it is not a widget. Instead, it stores a reference to the calculator form (the widget) in an instance variable, `ui`. The calculator script functions can access components of the form by referring to the proper children of the `ui` member.

    Calculator.prototype.digitClicked = function()
    {
        var digitValue = __qt_sender__.text - 0;
        if ((digitValue == 0) && (this.ui.display.text == "0"))
            return;
        if (this.waitingForOperand) {
            this.ui.display.clear();
            this.waitingForOperand = false;
        }
        this.ui.display.text += digitValue;
    }

The digitClicked() function uses the special local variable __qt_sender__ to access the object that triggered the signal; this gives us a simple way to retrieve the value of the digit that was clicked.

    Calculator.prototype.changeSignClicked = function()
    {
        var text = this.ui.display.text;
        var value = text - 0;

        if (value > 0) {
            text = "-" + text;
        } else if (value < 0) {
            text = text.slice(1);
        }
        this.ui.display.text = text;
    }

The changeSign() function shows how we retrieve the text property of the calculator's display, change it appropriately, and write back the new value.