Qt Reference Documentation

# QtScript Calculator Example

Files:

- script/calculator/calculator.js
- script/calculator/calculator.ui
- script/calculator/main.cpp
- script/calculator/calculator.pro
- script/calculator/calculator.qrc

In the QtScript Calculator 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.

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

- Create a widget from the UI file using QUiLoader.

           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.

           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.

           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 = Calculator.NO_OPERATOR;
         this.pendingMultiplicativeOperator = Calculator.NO_OPERATOR;
         this.sumInMemory = 0;
         this.sumSoFar = 0;
         this.factorSoFar = 0;
         this.waitingForOperand = true;

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

             zeroButton.clicked.connect(this.digitClicked.bind(this, 0));
             oneButton.clicked.connect(this.digitClicked.bind(this, 1));
             twoButton.clicked.connect(this.digitClicked.bind(this, 2));
             threeButton.clicked.connect(this.digitClicked.bind(this, 3));
             fourButton.clicked.connect(this.digitClicked.bind(this, 4));
             fiveButton.clicked.connect(this.digitClicked.bind(this, 5));
             sixButton.clicked.connect(this.digitClicked.bind(this, 6));
             sevenButton.clicked.connect(this.digitClicked.bind(this, 7));
             eightButton.clicked.connect(this.digitClicked.bind(this, 8));
             nineButton.clicked.connect(this.digitClicked.bind(this, 9));

             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.bind(this, Calculator.DIVISION_OPERATOR));
             timesButton.clicked.connect(this.multiplicativeOperatorClicked.bind(this, Calculator.TIMES_OPERATOR));
             minusButton.clicked.connect(this.additiveOperatorClicked.bind(this, Calculator.MINUS_OPERATOR));
             plusButton.clicked.connect(this.additiveOperatorClicked.bind(this, Calculator.PLUS_OPERATOR));

             squareRootButton.clicked.connect(this.unaryOperatorClicked.bind(this, Calculator.SQUARE_OPERATOR));
             powerButton.clicked.connect(this.unaryOperatorClicked.bind(this, Calculator.POWER_OPERATOR));
             reciprocalButton.clicked.connect(this.unaryOperatorClicked.bind(this, Calculator.RECIPROCAL_OPERATOR));
             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(digitValue)
     {
         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 is called when a digit button is clicked, with the input digit as argument.

     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.