Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Porting Programm with QScriptEngine to QJSEngine



  • I tryed to get this code running in QT5:

    https://github.com/cggos/CPPGUIProgrammingWithQt4/tree/master/chap22/htmleditor

    This Example uses QT4 with QScriptEngine.

    During runntime a javascript file interacts with a dialog in a ui file.

    So i have this ui:

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>StatisticsDialog</class>
     <widget class="QDialog" name="StatisticsDialog">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>255</width>
        <height>163</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>Statistics</string>
      </property>
      <layout class="QVBoxLayout">
       <item>
        <widget class="QFrame" name="frame">
         <property name="frameShape">
          <enum>QFrame::StyledPanel</enum>
         </property>
         <property name="frameShadow">
          <enum>QFrame::Raised</enum>
         </property>
         <layout class="QGridLayout">
          <item row="0" column="0">
           <widget class="QLabel" name="charCountLabel">
            <property name="text">
             <string>Number of characters:</string>
            </property>
           </widget>
          </item>
          <item row="0" column="1">
           <widget class="QLineEdit" name="charCountLineEdit">
            <property name="focusPolicy">
             <enum>Qt::NoFocus</enum>
            </property>
            <property name="text">
             <string/>
            </property>
            <property name="alignment">
             <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
            </property>
            <property name="readOnly">
             <bool>true</bool>
            </property>
           </widget>
          </item>
          <item row="1" column="0">
           <widget class="QLabel" name="wordCountLabel">
            <property name="text">
             <string>Number of words:</string>
            </property>
           </widget>
          </item>
          <item row="1" column="1">
           <widget class="QLineEdit" name="wordCountLineEdit">
            <property name="focusPolicy">
             <enum>Qt::NoFocus</enum>
            </property>
            <property name="text">
             <string/>
            </property>
            <property name="alignment">
             <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
            </property>
            <property name="readOnly">
             <bool>true</bool>
            </property>
           </widget>
          </item>
          <item row="2" column="0">
           <widget class="QLabel" name="lineCountLabel">
            <property name="text">
             <string>Number of lines:</string>
            </property>
           </widget>
          </item>
          <item row="2" column="1">
           <widget class="QLineEdit" name="lineCountLineEdit">
            <property name="focusPolicy">
             <enum>Qt::NoFocus</enum>
            </property>
            <property name="text">
             <string/>
            </property>
            <property name="alignment">
             <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
            </property>
            <property name="readOnly">
             <bool>true</bool>
            </property>
           </widget>
          </item>
         </layout>
        </widget>
       </item>
       <item>
        <layout class="QHBoxLayout">
         <item>
          <spacer>
           <property name="orientation">
            <enum>Qt::Horizontal</enum>
           </property>
           <property name="sizeHint" stdset="0">
            <size>
             <width>40</width>
             <height>20</height>
            </size>
           </property>
          </spacer>
         </item>
         <item>
          <widget class="QPushButton" name="closeButton">
           <property name="text">
            <string>Close</string>
           </property>
           <property name="default">
            <bool>true</bool>
           </property>
          </widget>
         </item>
         <item>
          <spacer>
           <property name="orientation">
            <enum>Qt::Horizontal</enum>
           </property>
           <property name="sizeHint" stdset="0">
            <size>
             <width>40</width>
             <height>20</height>
            </size>
           </property>
          </spacer>
         </item>
        </layout>
       </item>
      </layout>
     </widget>
     <resources/>
     <connections>
      <connection>
       <sender>closeButton</sender>
       <signal>clicked()</signal>
       <receiver>StatisticsDialog</receiver>
       <slot>accept()</slot>
       <hints>
        <hint type="sourcelabel">
         <x>154</x>
         <y>167</y>
        </hint>
        <hint type="destinationlabel">
         <x>210</x>
         <y>178</y>
        </hint>
       </hints>
      </connection>
     </connections>
    </ui>
    

    And this javascript code to show number of characters / number of words / number of lines from a QTextEdit

    var obj = new Object;
    
    obj.text = "&Statistics...";
    
    obj.run = function() {
        var text = this.textEdit.plainText;
        this.dialog.frame.charCountLineEdit.text = text.length;
        this.dialog.frame.wordCountLineEdit.text = this.wordCount(text);
        this.dialog.frame.lineCountLineEdit.text = this.lineCount(text);
        this.dialog.exec();
    };
    
    obj.wordCount = function(text) {
        var regExp = new RegExp("\\w+", "g");
        var count = 0;
        while (regExp.exec(text))
            ++count;
        return count;
    };
    
    obj.lineCount = function(text) {
        var count = 0;
        var pos = 0;
        while ((pos = text.indexOf("\n", pos)) != -1) {
            ++count;
            ++pos;
        }
        return count + 1;
    };
    
    return obj;
    

    QtCreator allready warns when i open the .js with "Return statement not allowed outside of Function dialog"

    In my mainwindow i handle the script code like this:

    void HtmlWindow::createScriptsMenu()
    {
        scriptsMenu = menuBar()->addMenu(tr("&Scripts"));
    
        auto scriptsDir = directoryOf("scripts");
        auto jsFileNames = scriptsDir.entryList(QStringList("*.js"),
                                                       QDir::Files);
        for (const auto &jsFileName : jsFileNames) {
            createScriptAction(scriptsDir.absoluteFilePath(jsFileName));
        }
    
        scriptsMenu->setEnabled(!scriptsMenu->isEmpty());
    }
    
    
    bool HtmlWindow::createScriptAction(const QString &jsFileName)
    {
        QFile jsFile(jsFileName);
        if (!jsFile.open(QIODevice::ReadOnly)) {
            QMessageBox::warning(this, tr("HTML Editor"),
                                 tr("Cannot read file %1:\n%2.")
                                 .arg(strippedName(jsFileName))
                                 .arg(jsFile.errorString()));
            return false;
        }
    
        QTextStream in(&jsFile);
        in.setCodec("UTF-8");
        auto script = in.readAll();
        jsFile.close();
    
        QJSValue qsScript = interpreter.evaluate(script);
    
        if (qsScript.isError()) {        
            reportScriptError(jsFileName, qsScript);
            return false;
        }
    
        QString uiFileName = jsFileName;
        uiFileName.chop(3);
        uiFileName += ".ui";
    
        QFile uiFile(uiFileName);
        if (!uiFile.open(QIODevice::ReadOnly)) {
            QMessageBox::warning(this, tr("HTML Editor"),
                                 tr("Cannot read file %1:\n%2.")
                                 .arg(strippedName(uiFileName))
                                 .arg(uiFile.errorString()));
            return false;
        }
    
        QUiLoader loader;
        QWidget *dialog = loader.load(&uiFile, this);
        uiFile.close();
        if (!dialog) {
            QMessageBox::warning(this, tr("HTML Editor"),
                                 tr("Error loading %1.")
                                 .arg(strippedName(uiFileName)));
            return false;
        }
    
        QJSValue qsDialog = interpreter.newQObject(dialog);
        qsScript.setProperty("dialog", qsDialog);
    
        QJSValue qsTextEdit = interpreter.newQObject(textEdit);
        qsScript.setProperty("textEdit", qsTextEdit);
    
        auto action = new QAction(this);
        action->setText(qsScript.property("text").toString());
        action->setData(QVariant::fromValue(qsScript));
        connect(action, &QAction::triggered,
                this, &HtmlWindow::scriptActionTriggered);
    
        scriptsMenu->addAction(action);
    
        return true;
    }
    
    void HtmlWindow::reportScriptError(const QString &fileName,
                                       const QJSValue &script)
    {
        QMessageBox messageBox(this);
        messageBox.setIcon(QMessageBox::Warning);
        messageBox.setWindowTitle(tr("HTML Editor"));
        messageBox.setText(tr("An error occurred while executing the "
                              "script %1.")
                           .arg(strippedName(fileName)));
    
        messageBox.setInformativeText(
                tr("%1.").arg(script.property("name").toString()));
        messageBox.setDetailedText(
                tr("Uncaught exception at line %1 : %2")
                    .arg(script.property("lineNumber").toInt())
                    .arg(script.toString()));
        messageBox.exec();
    }
    

    If I run the app i get the error ""Return statement not allowed outside of Function dialog" as well.

    So what to do to get this script code interpreted correctly?


Log in to reply