Pages
Developer Documentation
On this page

Command line interface

Introduction

The text editor can open and save files. Now let's make it behave more like a desktop application: open a file given on the command line, which also lets the file manager's "Open With" use it.

Code and explanation

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <KXmlGuiWindow>

class KTextEdit;
class KJob;

class MainWindow : public KXmlGuiWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    void openFileFromUrl(const QUrl &inputFileName);

private:
    void setupActions();
    void saveFileToDisk(const QString &outputFileName);

private Q_SLOTS:
    void newFile();
    void openFile();
    void saveFile();
    void saveFileAs();

    void downloadFinished(KJob *job);

private:
    KTextEdit *textArea;
    QString fileName;
};

#endif // MAINWINDOW_H

The only addition is a public function openFileFromUrl() that takes a QUrl. Again we use URLs rather than strings, so remote files work like local ones.

mainwindow.cpp

Only openFile() changes: it now passes the URL from the dialog to the new openFileFromUrl(), which contains the rest of the old openFile():

void MainWindow::openFile()
{
    openFileFromUrl(QFileDialog::getOpenFileUrl(this, i18n("Open File")));
}

void MainWindow::openFileFromUrl(const QUrl &inputFileName)
{
    if (!inputFileName.isEmpty()) {
        KIO::Job *job = KIO::storedGet(inputFileName);
        fileName = inputFileName.toLocalFile();
        connect(job, &KJob::result, this, &MainWindow::downloadFinished);
        job->exec();
    }
}

The rest of mainwindow.cpp is as in Saving and loading. There's no new code, only rearranging: we call openFile() to show a dialog, or openFileFromUrl() when we already know the file, as we do when it is given on the command line.

main.cpp

#include <QApplication>
#include <QCommandLineParser>
#include <QDir>
#include <QUrl>
#include <KAboutData>
#include <KLocalizedString>
#include "mainwindow.h"

int main (int argc, char *argv[])
{
    using namespace Qt::Literals::StringLiterals;

    QApplication app(argc, argv);
    KLocalizedString::setApplicationDomain("texteditor");

    KAboutData aboutData(
        u"texteditor"_s,
        i18n("Text Editor"),
        u"1.0"_s,
        i18n("A simple text area which can load and save."),
        KAboutLicense::GPL,
        i18n("(c) 2024"),
        i18n("Educational application..."),
        u"https://example.com/texteditor/"_s,
        u"https://example.com/texteditor/bugs/"_s);

    aboutData.addAuthor(
        i18n("John Doe"),
        i18n("Tutorial learner"),
        u"john.doe@example.com"_s,
        u"https://john-doe.example.com"_s,
        u"johndoe"_s);

    KAboutData::setApplicationData(aboutData);

    QCommandLineParser parser;
    aboutData.setupCommandLine(&parser);
    parser.addPositionalArgument(u"file"_s, i18n("Document to open"));

    parser.process(app);
    aboutData.processCommandLine(&parser);

    MainWindow *window = new MainWindow();
    window->show();

    if (parser.positionalArguments().count() > 0) {
        window->openFileFromUrl(QUrl::fromUserInput(
            parser.positionalArguments().at(0),
            QDir::currentPath()));
    }

    return app.exec();
}

This is where QCommandLineParser does its work. So far we only used it to give the application options like --version and --author; now it processes arguments too.

First we tell it about a positional argument. Positional arguments are the arguments that aren't options: -h and --version are options, file is an argument.

parser.addPositionalArgument(u"file"_s, i18n("Document to open"));

After processing, if there is an argument, we open it; otherwise we carry on as before. The editor opens one file at a time, so only the first argument matters. We pass openFileFromUrl() the URL of the file, whether local, like $HOME/foo, or remote, like ftp://ftp.example.com/bar. The form of QUrl::fromUserInput() with a working directory resolves relative paths such as ../baz against the current directory.

if (parser.positionalArguments().count() > 0) {
    window->openFileFromUrl(QUrl::fromUserInput(parser.positionalArguments().at(0), QDir::currentPath()));
}

CMakeLists.txt

Nothing changes; it is the same as in Saving and loading.

Running the application

Build and install it as in Hello World.

Then check that the application opens files from the command line. Create a simple file:

echo "It works!" > testfile.txt

and pass it as an argument:

texteditor testfile.txt

The editor starts and shows "It works!" in the text area.

This was the last step of the tutorial. You now have a small text editor that loads and saves local and remote files, with menus, a toolbar, shortcuts and a command line.

Adapted for SonicDE from develop.kde.org/docs/getting-started/kxmlgui/commandline/ by Albert Astals Cid, Alexander Lohnau, Andrew Shark, Burak Hancerli, Carl Schwan, Claudio Cambra, Enzo Barcelos, Mikhail Zolotukhin, Thiago Sueto, licensed under CC BY-SA 4.0.

Edit this page on GitHub

We use cookies to personalize content and to analyze our traffic. Please decide if you are willing to accept cookies from our website.