8

QML at the moment lacks basic system commands, so I am looking for the most simple template to write to /tmp/text.txt.

Anon
  • 11,863
  • 22
  • 66
  • 122

3 Answers3

5

There is no way to write to a file from QML/Javascript so we need a bit of C++ to do the job.

Create a new Qt Quick 2 Application (Built-in Elements) project in Qt Creator called FileIO with the following files:

The project file: FileIO.pro

# The .cpp file which was generated for your project. Feel free to hack it.
SOURCES += main.cpp

# Please do not modify the following two lines. Required for deployment.
include(qtquick2applicationviewer/qtquick2applicationviewer.pri)
qtcAddDeployment()

HEADERS += fileio.h

The header file: fileio.h (inspired by Reading and writing files in QML)

#ifndef FILEIO_H
#define FILEIO_H

#include <QObject>
#include <QFile>
#include <QTextStream>

class FileIO : public QObject
{
    Q_OBJECT

public slots:
    bool write(const QString& source, const QString& data)
    {
        if (source.isEmpty())
            return false;

        QFile file(source);
        if (!file.open(QFile::WriteOnly | QFile::Truncate))
            return false;

        QTextStream out(&file);
        out << data;
        file.close();
        return true;
    }

public:
    FileIO() {}
};

#endif // FILEIO_H

main.cpp:

#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QQmlContext>
#include "fileio.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    FileIO fileIO;

    QtQuick2ApplicationViewer viewer;
    viewer.rootContext()->setContextProperty("fileio", &fileIO);
    viewer.setMainQmlFile(QStringLiteral("qml/FileIO/main.qml"));
    viewer.showExpanded();

    return app.exec();
}

And finally qml/FileIO/main.qml:

import QtQuick 2.0

Rectangle {
    width: 360
    height: 360
    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            fileio.write("/tmp/test", "Ask Ubuntu");
            Qt.quit();
        }
    }
}

To build the application, open a Terminal and go to the FileIO project folder to type:

`qmake && make && ./FileIO`.

It will launch the application. If you click on the MainView the text file will be created and the application closed.

Update:

The above code will work without restrictions for a desktop application. Regarding write permissions for Ubuntu Touch, you'll have to follow the guidelines about Confinement for click packages:

The application will have read/write access files in the standard XDG base directories. Specifically:

XDG_CACHE_HOME/<APP_PKGNAME>
XDG_CONFIG_HOME/<APP_PKGNAME>
XDG_DATA_HOME/<APP_PKGNAME>
XDG_RUNTIME_DIR/confined/<APP_PKGNAME>

where APP_PKGNAME is what is used in the "name" field of the click manifest. Eg, if the click manifest has this:

$ cat ./manifest.json
{
  "name": "com.ubuntu.developer.you.yourapp",
  ...
}

then the app will have read/write access to these directories and any files or subdirectories under them:

XDG_CACHE_HOME/com.ubuntu.developer.you.yourapp
XDG_CONFIG_HOME/com.ubuntu.developer.you.yourapp
XDG_DATA_HOME/com.ubuntu.developer.you.yourapp
XDG_RUNTIME_DIR/confined/com.ubuntu.developer.you.yourapp
Sylvain Pineau
  • 61,564
  • 18
  • 149
  • 183
  • 1
    Are you sure that you selected New Qt Quick 2 Application, the main.cpp should be there (tested on both 13.10 and 14.04). it's Applications->Qt Quick 2 Application (Built-in Elements) for 13.10 and Applications->Qt Quick Application->Qt Quick 2 for 14.04 – Sylvain Pineau Apr 26 '14 at 20:06
  • mmmm, yah its not there. http://i.imgur.com/rffyRGF.jpg And I just updated my sdk package today. You must have some extra libs installed by default. – Anon Apr 26 '14 at 20:14
  • 1
    Wait a minute, it's well there in your screenshot, the second item, Qt Quick Application – Sylvain Pineau Apr 26 '14 at 20:24
  • The description is a bit confusing then, and I presume its just because you have some legacy aspects from the sdk; http://i.imgur.com/6wp1zeJ.jpg Qt Quick 2 is not mentioned, the header file as you described it is not included, and the supported platform only says "Desktop", where as this is for ubuntu-touch. – Anon Apr 26 '14 at 20:33
  • 1
    Actually, after selecting "Qt Quick Application", you have to enter the project name and path and after this step you can choose "Qt Quick2" in the drop-down list (14.04 behavior) – Sylvain Pineau Apr 26 '14 at 20:36
  • 1
    You're right for the fileio.h, you need to create this one manually. – Sylvain Pineau Apr 26 '14 at 20:37
  • Will it be usable with ubuntu touch on the phone? – Anon Apr 26 '14 at 20:38
  • let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/14158/discussion-between-akiva-and-sylvain-pineau) – Anon Apr 26 '14 at 20:40
  • I've updated my answer to cover Ubuntu touch confinement, could you please reconsider accepting it again? thanks. – Sylvain Pineau Apr 27 '14 at 15:18
  • @Akiva: Now with details about confinement, could you accept this answer? I'd like to know what's missing – Sylvain Pineau Apr 30 '14 at 09:05
  • Oh sorry; I have been meaning to add my own solution, which I think is better. It basically amounts to this http://imgur.com/NxSId9k – Anon Apr 30 '14 at 09:09
  • 1
    I see, thanks for improving the list of possible solutions! – Sylvain Pineau Apr 30 '14 at 09:11
  • Added the solution below. Let me know what you think. – Anon Apr 30 '14 at 10:06
  • Worked flawlessly. Btw, to write Json to that file, use: `fileio.write("path/to/file.json", JSON.stringify(jsonObj));` Thanks for posting your answer! – phyatt Jul 05 '16 at 01:37
4

New File or Project. Choose the QML App with C++ Plugin. qmake is generally easier to pick up than cmake. New File or Project

Choose a name for your project. Next. Choose a name for your project

Usually you can just choose the default framework selected. Next. Usually you can just choose the default framework selected.

Add Bazaar Version Control, as it works well with Launchpad. You can try Git too if you are familiar with it. Launchpad supports both, but Git support is still pretty new as of July 2016. Add Bazaar Version Control, as it works well with Launchpad.

Edit your header, adding the three lines from the comments. Edit your header, adding the three lines from the comments.

Edit your source, adding just the function on the bottom. Edit your source, adding just the function on the bottom.

Edit your Main.qml file, adding just the component on the bottom. Edit your Main.qml file, adding just the component on the bottom.

Run your application, and find the text file in your build directory. The build directory is in the same directory of your project directory, and it has the word "build-" prefixed to the beginning. Run your application, and find the text file in your build directory.

Anon
  • 11,863
  • 22
  • 66
  • 122
  • 1
    Can you please explain the 4th step to me? You name the qml file with same name with that of the project and then import the same name in the qml file? Mind = fucked – Akash Agarwal Jul 17 '16 at 18:47
  • This is a slight bit out of date, as the template is called something else now, but generally, if you create a new project and call it foobar, that file i am talking about will be foobar.qml. that being said, you can use any name, that shouldn't matter. – Anon Jul 17 '16 at 19:57
  • 1
    I majorly didn't understand importing 'foobar ' in foobar.qml – Akash Agarwal Jul 17 '16 at 19:59
  • Do you get it now? – Anon Jul 17 '16 at 20:02
  • 1
    It appears that you haven't made any change to anything since my last comment so no, sorry. – Akash Agarwal Jul 17 '16 at 20:04
  • @AkashAggarwal -- I updated the tutorial for you. Tested it on my machine. Should be much easier to follow now. – Anon Jul 17 '16 at 23:27
  • 1
    Thanks for going so far trying to explain things to me. Unfortunately the question I've been asking is still not answered. What is the use of `import Foobar 1.0`? + Don't you need to register it first in `main.cpp` using `qmlRegisterType<>()` method? – Akash Agarwal Jul 17 '16 at 23:56
  • @AkashAggarwal `qmlRegisterType<>()` I do remember using that way back, however I forget the exact reason I stopped using it. It may even be deprecated by the `.pro` file (That used to not exist, because the old projects were using cmakelist), but do not take my word for it. In any case, the macro `Q_INVOKABLE` does seem to take care of the function, and the `import Foobar 1.0` is automatically generated by the template. Sorry I can't be of more help. – Anon Jul 18 '16 at 00:27
  • 1
    Thanks! You might want to check this out for your own knowledge; read the 2nd answer: http://stackoverflow.com/questions/38423590/cant-figure-out-the-right-way-to-bind-signals-from-qml-to-cpp-slots – Akash Agarwal Jul 18 '16 at 06:24
0

Just to clarify Confinement Policy, if you want to write a file on Ubuntu Touch, in your file mytype.cpp, replace:

QString filename = "text.txt";

by:

QString filename = "/home/phablet/.local/share/your_app_name/text.txt";