Development/Tutorials/Kross/Call Functions in Kross: Difference between revisions

    From KDE TechBase
    No edit summary
    No edit summary
    Line 3: Line 3:
    == The source files ==
    == The source files ==


    This tutorial is based on the [[Development/Tutorials/Kross/Hello_World|Hello World]] tutorial and extends the codebase we wrote there with new functionality.
    This tutorial is based on the [[Development/Tutorials/Kross/Hello_World|Hello World]] tutorial and extends the codebase we wrote there with new functionality to outline how calling scripting functions could be done.
     
    Please note, that it is recommed to use [[Development/Tutorials/Kross/Connecting_Signals_and_slots_in_Kross#Autoconnecting_Signals_and_Slots Autoconnected Signals and Slots]] if you just like to have a bunch of scripting functions within a script that should be called on demand. That way you have a clear interface with signals that are mapped transparent to scripting functions. The "trick" here is, that Kross will automaticly connect each signal a QObject has to a matching scripting function and at the C++ side all what is
    needed is to emit a signal and behind the scene the arguments will be
    translated and a possible defined scripting function got called.


    === CMakeLists.txt ===
    === CMakeLists.txt ===
    Line 32: Line 36:


    int main (int argc, char *argv[]) {
    int main (int argc, char *argv[]) {
    // Used to store information about a program.
        // Used to store information about a program.
    KAboutData aboutData("krosshello",
        KAboutData aboutData("krosshello",
    0,
            0,ki18n("Kross Hello World"),"1.0",
    ki18n("Kross Hello World"),
    ki18n("Hello World application for Kross"),
    "1.0",
    KAboutData::License_GPL,
    ki18n("Hello World application for Kross"),
    ki18n("(c) 2007"),ki18n("Some text..."),
    KAboutData::License_GPL,
    "http://kross.dipe.org","[email protected]");
    ki18n("(c) 2007"),
        // Access to the command-line arguments.
    ki18n("Some text..."),
        KCmdLineArgs::init( argc, argv, &aboutData );
    "http://kross.dipe.org",
        // Initialize the application.
        KApplication app;
    // Access to the command-line arguments.
        // Create and show the main window.
    KCmdLineArgs::init( argc, argv, &aboutData );
        MainWindow* window = new MainWindow();
    // Initialize the application.
        window->show();
    KApplication app;
        // Finally execute the application.
    // Create and show the main window.
        return app.exec();
    MainWindow* window = new MainWindow();
    window->show();
    // Finally execute the application.
    return app.exec();
    }
    }
    </code>
    </code>


    === mainwindow.h ===
    === mainwindow.h ===
    This is the main windows class which defines some displayed widgets for our small sample application.


    <code cpp>
    <code cpp>
    Line 69: Line 71:
    class MainWindow : public QWidget
    class MainWindow : public QWidget
    {
    {
    Q_OBJECT
        Q_OBJECT
    public:
        public:
    MainWindow(QWidget *parent=0);
            MainWindow(QWidget *parent=0);
    private Q_SLOTS:
        private Q_SLOTS:
    // This slot is called when the item in the combobox is changed.
            // This slot is called when the item in the combobox is changed.
    void interpreterActivated(const QString &);
            void interpreterActivated(const QString &);
    private:
        private:
    QLineEdit* txtInputString;
            QLineEdit* txtInputString;
    QLabel* lblMessage;
    QLabel* lblMessage;
    QComboBox* cmbInterpreters;
    QComboBox* cmbInterpreters;
    Kross::Action* action;
    Kross::Action* action;
    };
    };


    Line 86: Line 88:


    === mainwindow.cpp ===
    === mainwindow.cpp ===
    The implementation of the main window functionality. We are displaying a QLineEdit that will be passed as first argument to a scripting function named "reverseString". Those function returns a string that will then displayed in a QLabel. Just like at the [[Development/Tutorials/Kross/Hello World|Kross Hello World]] tutorial, we also display a QComboBox that does allow to choose an interpreter. Though this sample does provide only one sample script written in JavaScript to demonstrate the usage.


    <code cpp>
    <code cpp>
    Line 97: Line 101:
    MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
    MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
    {
    {
    txtInputString = new QLineEdit();
        txtInputString = new QLineEdit();
    lblMessage = new QLabel("Hello");
        lblMessage = new QLabel("Hello");
    cmbInterpreters = new QComboBox ();
        cmbInterpreters = new QComboBox ();
    cmbInterpreters->addItem("Choose Interpreter", "");
        cmbInterpreters->addItem("Choose Interpreter", "");
     
        foreach(QString s, Kross::Manager::self().interpreters())
    foreach(QString s, Kross::Manager::self().interpreters())
            cmbInterpreters->addItem(s);
    cmbInterpreters->addItem(s);


    connect(cmbInterpreters, SIGNAL(activated(const QString &)),
        connect(cmbInterpreters, SIGNAL(activated(const QString &)),
    SLOT(interpreterActivated(const QString &)));
                SLOT(interpreterActivated(const QString &)));


    QVBoxLayout *vLayout = new QVBoxLayout;
        QVBoxLayout *vLayout = new QVBoxLayout;
    vLayout->addWidget(cmbInterpreters);
        vLayout->addWidget(cmbInterpreters);
    vLayout->addWidget(txtInputString);
        vLayout->addWidget(txtInputString);
    vLayout->addWidget(lblMessage);
        vLayout->addWidget(lblMessage);
    setLayout(vLayout);
        setLayout(vLayout);


    // Create the Kross::Action instance and publish some
        // Create the Kross::Action instance and publish some
    // QObject instances.
        // QObject instances.
    action = new Kross::Action(this, "MyScript");
        action = new Kross::Action(this, "MyScript");
    action->addObject(txtInputString, "MyInputString");
        action->addObject(txtInputString, "MyInputString");
    action->addObject(cmbInterpreters, "MyInterpreter");
        action->addObject(cmbInterpreters, "MyInterpreter");
    action->addObject(lblMessage, "MyLabel");
        action->addObject(lblMessage, "MyLabel");
    }
    }


    Line 125: Line 128:
    void MainWindow::interpreterActivated(const QString &strSelectedInterpreter)
    void MainWindow::interpreterActivated(const QString &strSelectedInterpreter)
    {
    {
    // this time we are using external script files.
        // this time we are using external script files.
    // at this sample we are only using JavaScript but
        // at this sample we are only using JavaScript but
    // other supported backends will work well too.
        // other supported backends will work well too.
    if(strSelectedInterpreter != "javascript") {
        if(strSelectedInterpreter != "javascript") {
    lblMessage->setText("-");
            lblMessage->setText("-");
    return;
            return;
    }
        }


    // set the script file that should be executed
        // set the script file that should be executed
    action->setFile("Testscriptfile.js");
        action->setFile("Testscriptfile.js");


    // execute the scripting code, i.e. preload
        // execute the scripting code, i.e. preload
    action->trigger();
        // please note, that it's needed to trigger aka
        // execute the script before calling a function
        // using callFunction() or before asking what
        // functions are available using functionNames().
        action->trigger();


    // now we can call arbitrary functions
        // now we can call arbitrary functions
    QVariantList arguments;
        QVariantList args;


    // here we pass in the QLineEdit instance as argument.
        // here we pass in the QLineEdit instance as argument.
    QVariant v;
        QVariant v;
    v.setValue( (QWidget*) txtInputString );
        v.setValue( (QWidget*) txtInputString );
    arguments << v;
        args << v;


    // and the second argument is a string
        // and the second argument is a string
    arguments << "Hello World";
        args << "Hello World";


    // Call the function
        // Call the function
    QVariant result = action->callFunction("reverseString", arguments);
        QVariant result = action->callFunction("reverseString", args);


    // Use the returnvalue of the function call
        // Use the returnvalue of the function call
    lblMessage->setText(result.toString());
        lblMessage->setText(result.toString());
    }
    }
    </code>
    </code>

    Revision as of 22:02, 16 January 2008

    This tutorial shows how to deal with functions provided by a script. It builds upon the Kross Hello World tutorial.

    The source files

    This tutorial is based on the Hello World tutorial and extends the codebase we wrote there with new functionality to outline how calling scripting functions could be done.

    Please note, that it is recommed to use Development/Tutorials/Kross/Connecting_Signals_and_slots_in_Kross#Autoconnecting_Signals_and_Slots Autoconnected Signals and Slots if you just like to have a bunch of scripting functions within a script that should be called on demand. That way you have a clear interface with signals that are mapped transparent to scripting functions. The "trick" here is, that Kross will automaticly connect each signal a QObject has to a matching scripting function and at the C++ side all what is needed is to emit a signal and behind the scene the arguments will be translated and a possible defined scripting function got called.

    CMakeLists.txt

    We are using cmake to build our small sample project. The CMakeLists.txt file looks like;

    project (krosshello) find_package(KDE4 REQUIRED) include_directories( ${KDE4_INCLUDES} ) set(krosshello_SRCS main.cpp mainwindow.cpp) kde4_add_executable(krosshello ${krosshello_SRCS}) target_link_libraries(krosshello ${KDE4_KDEUI_LIBS} ${KDE4_KROSSUI_LIBS})

    main.cpp

    The main.cpp does create the sample application and shows the mainwindow instance.

    1. include <QString>
    2. include <KApplication>
    3. include <KAboutData>
    4. include <KMessageBox>
    5. include <KCmdLineArgs>
    6. include <KLocalizedString>
    7. include "mainwindow.h"

    int main (int argc, char *argv[]) {

       // Used to store information about a program.
       KAboutData aboutData("krosshello",
           0,ki18n("Kross Hello World"),"1.0",
    

    ki18n("Hello World application for Kross"), KAboutData::License_GPL, ki18n("(c) 2007"),ki18n("Some text..."), "http://kross.dipe.org","[email protected]");

       // Access to the command-line arguments.
       KCmdLineArgs::init( argc, argv, &aboutData );
       // Initialize the application.
       KApplication app;
       // Create and show the main window.
       MainWindow* window = new MainWindow();
       window->show();
       // Finally execute the application.
       return app.exec();
    

    }

    mainwindow.h

    This is the main windows class which defines some displayed widgets for our small sample application.

    1. ifndef MAINWINDOW_H
    2. define MAINWINDOW_H
    1. include <QComboBox>
    2. include <QLabel>
    3. include <QLineEdit>
    4. include <kross/core/action.h>

    // The main window to display our combobox and the label. class MainWindow : public QWidget {

       Q_OBJECT
       public:
           MainWindow(QWidget *parent=0);
       private Q_SLOTS:
           // This slot is called when the item in the combobox is changed.
           void interpreterActivated(const QString &);
       private:
           QLineEdit* txtInputString;
    

    QLabel* lblMessage; QComboBox* cmbInterpreters; Kross::Action* action; };

    1. endif

    mainwindow.cpp

    The implementation of the main window functionality. We are displaying a QLineEdit that will be passed as first argument to a scripting function named "reverseString". Those function returns a string that will then displayed in a QLabel. Just like at the Kross Hello World tutorial, we also display a QComboBox that does allow to choose an interpreter. Though this sample does provide only one sample script written in JavaScript to demonstrate the usage.

    1. include "mainwindow.h"
    2. include <QVBoxLayout>
    3. include <QDebug>
    4. include <kross/core/manager.h>
    5. include <kross/core/action.h>

    // the constructor. MainWindow::MainWindow(QWidget *parent) : QWidget(parent) {

       txtInputString = new QLineEdit();
       lblMessage = new QLabel("Hello");
       cmbInterpreters = new QComboBox ();
       cmbInterpreters->addItem("Choose Interpreter", "");
       foreach(QString s, Kross::Manager::self().interpreters())
           cmbInterpreters->addItem(s);
    
       connect(cmbInterpreters, SIGNAL(activated(const QString &)),
               SLOT(interpreterActivated(const QString &)));
    
       QVBoxLayout *vLayout = new QVBoxLayout;
       vLayout->addWidget(cmbInterpreters);
       vLayout->addWidget(txtInputString);
       vLayout->addWidget(lblMessage);
       setLayout(vLayout);
    
       // Create the Kross::Action instance and publish some
       // QObject instances.
       action = new Kross::Action(this, "MyScript");
       action->addObject(txtInputString, "MyInputString");
       action->addObject(cmbInterpreters, "MyInterpreter");
       action->addObject(lblMessage, "MyLabel");
    

    }

    // this slot is called when the active item of the combobox changes. void MainWindow::interpreterActivated(const QString &strSelectedInterpreter) {

       // this time we are using external script files.
       // at this sample we are only using JavaScript but
       // other supported backends will work well too.
       if(strSelectedInterpreter != "javascript") {
           lblMessage->setText("-");
           return;
       }
    
       // set the script file that should be executed
       action->setFile("Testscriptfile.js");
    
       // execute the scripting code, i.e. preload
       // please note, that it's needed to trigger aka
       // execute the script before calling a function
       // using callFunction() or before asking what
       // functions are available using functionNames().
       action->trigger();
    
       // now we can call arbitrary functions
       QVariantList args;
    
       // here we pass in the QLineEdit instance as argument.
       QVariant v;
       v.setValue( (QWidget*) txtInputString );
       args << v;
    
       // and the second argument is a string
       args << "Hello World";
    
       // Call the function
       QVariant result = action->callFunction("reverseString", args);
    
       // Use the returnvalue of the function call
       lblMessage->setText(result.toString());
    

    }

    Testscriptfile.js

    The following JavaScript file does provide us the reverseString function. This function will be executed at the mainwindow.cpp file.

    function reverseString(lineedit, s) {

       println("reverseString lineedit=" + lineedit + " s=" + s);
    
       lineedit.setText("Text to reverse: " +s);
       //MyInputString.text = "Text to reverse: " +s;
    
       return s.split("").reverse().join("");
    

    }