|  | Home · All Classes · Main Classes · Grouped Classes · Modules · Functions |

# 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 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.

           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.

           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 = "";
         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.