Development/Tutorials/KCmdLineArgs/KF5

    From KDE TechBase


    Command line arguments (Under construction User:milliams)
    Tutorial Series   Beginner Tutorial
    Previous   Tutorial 4 - Loading and saving
    What's Next   Tutorial 6 - ### (TODO User:milliams)
    Further Reading   KCmdLineArgs KCmdLineOptions


    Abstract

    Rough draft of port to KDE Frameworks 5.

    This is a very rough work in progresss. The port to KIO code still needs to be double checked and random freezes with QFileDialog still need to be resolved.


    The Code

    main.cpp

    #include <cstdlib>
     
    #include <QApplication>
    #include <QCommandLineParser>
    
    #include <KAboutData>
    #include <KLocalizedString>
    
    #include "mainwindow.h"
     
    int main (int argc, char *argv[])
    {
        QApplication app(argc, argv);
        
        KLocalizedString::setApplicationDomain("tutorial5");
        
        KAboutData aboutData(
                             // The program name used internally. (componentName)
                             QStringLiteral("tutorial5"),
                             // A displayable program name string. (displayName)
                             i18n("Tutorial 5"),
                             // The program version string. (version)
                             QStringLiteral("1.0"),
                             // Short description of what the app does. (shortDescription)
                             i18n("A simple text area which can load and save."),
                             // The license this code is released under
                             KAboutLicense::GPL,
                             // Copyright Statement (copyrightStatement = QString())
                             i18n("(c) 2015"),
                             // Optional text shown in the About box.
                             // Can contain any information desired. (otherText)
                             i18n("Some text..."),
                             // The program homepage string. (homePageAddress = QString())
                             QStringLiteral("http://example.com/"),
                             // The bug report email address
                             // (bugsEmailAddress = QLatin1String("[email protected]")
                             QStringLiteral("[email protected]"));
        aboutData.addAuthor(i18n("Name"), i18n("Task"), QStringLiteral("[email protected]"),
                            QStringLiteral("http://your.website.com"), QStringLiteral("OSC Username"));
        KAboutData::setApplicationData(aboutData);
     
        QCommandLineParser parser;
        parser.addHelpOption();
        parser.addVersionOption();
        // 1
        parser.addPositionalArgument(QStringLiteral("file"), i18n("Document to open"));
        
        aboutData.setupCommandLine(&parser);
        parser.process(app);
        
        aboutData.processCommandLine(&parser);
        
        MainWindow* window = new MainWindow();
        window->show();
        
        if (parser.positionalArguments().count() > 0)
        {
            window->openFile(parser.positionalArguments().at(0));
        }
        
        return app.exec();
    }
    

    Notes

    1. KCmdLineArgs is deprecated, use QCommandLineParser instead - https://community.kde.org/Frameworks/Porting_Notes#KCmdLineArgs

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
     
    #include <KXmlGuiWindow>
    
    class KTextEdit;
    class KJob;
     
    class MainWindow : public KXmlGuiWindow
    {
        Q_OBJECT
        
      public:
        MainWindow(QWidget *parent=0);
        // 1
        void openFile(const QString &inputFileName);
     
      private:
        KTextEdit* textArea;
        void setupActions();
        
        QString fileName;
     
      private slots:
        void newFile();
        void openFile();
        void saveFile();
        void saveFileAs();
        void saveFileAs(const QString &outputFileName);
        
        void downloadFinished(KJob* job);
    };
     
    #endif
    

    Notes

    1. expose an openFile method to main.cpp

    mainwindow.cpp

    #include <QApplication>
    #include <QAction>
    // 1
    #include <QSaveFile>
    // 2
    #include <QFileDialog>
    #include <QTextStream>
    #include <QByteArray>
    
    #include <KTextEdit>
    #include <KLocalizedString>
    #include <KActionCollection>
    #include <KStandardAction>
    #include <KMessageBox>
    // 3
    #include <KIO/Job>
    
    #include "mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) : KXmlGuiWindow(parent)
    {
      textArea = new KTextEdit();
      setCentralWidget(textArea);
      
      setupActions();
    }
    
    void MainWindow::setupActions()
    {
        QAction* clearAction = new QAction(this);
        clearAction->setText(i18n("&Clear"));
        // 4
        clearAction->setIcon(QIcon::fromTheme("document-new"));
        // 5
        actionCollection()->setDefaultShortcut(clearAction, Qt::CTRL + Qt::Key_W);
        actionCollection()->addAction("clear", clearAction);
        connect(clearAction, SIGNAL(triggered(bool)), textArea, SLOT(clear()));
        
        // 6
        KStandardAction::quit(qApp, SLOT(quit()), actionCollection());
        
        KStandardAction::open(this, SLOT(openFile()), actionCollection());
     
        KStandardAction::save(this, SLOT(saveFile()), actionCollection());
     
        KStandardAction::saveAs(this, SLOT(saveFileAs()), actionCollection());
     
        KStandardAction::openNew(this, SLOT(newFile()), actionCollection());
        
        setupGUI(Default, "tutorial5ui.rc");
    }
    
    void MainWindow::newFile()
    {
        fileName.clear();
        textArea->clear();
    }
    
    void MainWindow::saveFileAs(const QString &outputFileName)
    {
        if (!outputFileName.isNull())
        {
            QSaveFile file(outputFileName);
            file.open(QIODevice::WriteOnly);
            
            QByteArray outputByteArray;
            outputByteArray.append(textArea->toPlainText().toUtf8());
            file.write(outputByteArray);
            file.commit();
    
            fileName = outputFileName;
        }
    }
    
    void MainWindow::saveFileAs()
    {
        saveFileAs(QFileDialog::getSaveFileName(this, i18n("Save File As")));
    }
    
    void MainWindow::saveFile()
    {
        if (!fileName.isEmpty())
        {
            saveFileAs(fileName);
        }
        else
        {
            saveFileAs();
        }
    }
    
    
    void MainWindow::openFile()
    {
        openFile(QFileDialog::getOpenFileName(this, i18n("Open File")));
    }
        
    void MainWindow::openFile(const QString &inputFileName)
    {
        
        if (!inputFileName.isNull())
        {
            KIO::Job* job = KIO::storedGet(QUrl::fromUserInput(inputFileName));
            fileName = inputFileName;
    
            connect(job, SIGNAL(result(KJob*)), this, SLOT(downloadFinished(KJob*)));
            
            job->exec();
        }
    }
    
    void MainWindow::downloadFinished(KJob* job)
    {
        if (job->error())
        {
            KMessageBox::error(this, job->errorString());
            fileName.clear();
            return;
        }
        
        KIO::StoredTransferJob* storedJob = (KIO::StoredTransferJob*)job;
        textArea->setPlainText(QTextStream(storedJob->data(), QIODevice::ReadOnly).readAll());
    }
    

    tutorial5ui.rc

    <?xml version="1.0" encoding="UTF-8"?>
    <gui name="tutorial5"
         version="1"
         xmlns="http://www.kde.org/standards/kxmlgui/1.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0
                             http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd" >
     
      <MenuBar>
        <Menu name="file" >
          <Action name="clear" />
        </Menu>
      </MenuBar>
     
      <ToolBar name="mainToolBar" >
        <text>Main Toolbar</text>
        <Action name="clear" />
      </ToolBar>
     
    </gui>
    

    Make, Install and Run

    CMakeLists.txt

    project (tutorial5)
    
    cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
    set(QT_MIN_VERSION "5.3.0")
    set(KF5_MIN_VERSION "5.2.0")
    
    find_package(ECM 1.0.0 REQUIRED NO_MODULE)
    set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
    
    include(KDEInstallDirs)
    include(KDECMakeSettings)
    include(KDECompilerSettings)
    include(FeatureSummary)
    
    # Find Qt modules
    find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS 
        Core    # QCommandLineParser, QStringLiteral, QSaveFile, QTextStream, QByteArray
        Widgets # QApplication, QAction, QFileDialog
    )
    
    # Find KDE modules
    find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
        CoreAddons      # KAboutData
        I18n            # KLocalizedString
        XmlGui          # KXmlGuiWindow, KActionCollection
        TextWidgets     # KTextEdit
        ConfigWidgets   # KStandardActions
        WidgetsAddons   # KMessageBox
        KIO             # KIO
    )
        
    
    feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
        
    set(tutorial5_SRCS main.cpp mainwindow.cpp)
    
    # just plain add_executable
    add_executable(tutorial5 ${tutorial5_SRCS})
    
    # module-based linking
    target_link_libraries(tutorial5
        Qt5::Widgets
        KF5::CoreAddons
        KF5::I18n
        KF5::XmlGui
        KF5::TextWidgets
        KF5::ConfigWidgets
        KF5::WidgetsAddons
        KF5::KIOCore
    )
    
    install(TARGETS tutorial5  ${INSTALL_TARGETS_DEFAULT_ARGS})
    
    install(FILES tutorial5ui.rc DESTINATION ${KXMLGUI_INSTALL_DIR}/tutorial5)