Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. run a sh shell while clicking button in QML with QT5.15.0
Forum Updated to NodeBB v4.3 + New Features

run a sh shell while clicking button in QML with QT5.15.0

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
22 Posts 7 Posters 6.7k Views 4 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L lxy12345

    @jsulm Hi, jsulm. I have tried your post but I misunderstand somewhere maybe.
    I don't understand the singal "onReadyRead", I googled which said that this signal is for TCP/IP??? I am not very sure about that.
    what and where should I modify in your post?

    mrjjM Offline
    mrjjM Offline
    mrjj
    Lifetime Qt Champion
    wrote on last edited by
    #10

    @lxy12345 said in run a sh shell while clicking button in QML with QT5.15.0:

    onReadyRead

    Hi
    Its also for other things.
    " QProcess emits readyRead() when data is available on the current read channel. It also emits readyReadStandardOutput() when new standard output data is available"

    https://doc.qt.io/qt-5/qprocess.html
    in the Communicating via Channels section

    L 1 Reply Last reply
    0
    • mrjjM mrjj

      @lxy12345 said in run a sh shell while clicking button in QML with QT5.15.0:

      onReadyRead

      Hi
      Its also for other things.
      " QProcess emits readyRead() when data is available on the current read channel. It also emits readyReadStandardOutput() when new standard output data is available"

      https://doc.qt.io/qt-5/qprocess.html
      in the Communicating via Channels section

      L Offline
      L Offline
      lxy12345
      wrote on last edited by
      #11

      @jsulm when I tried the code ,
      Text {
      id: text
      }

      Process{
          id: process
           onReadyRead: text.text = readAll();
      }
      Timer {
           interval: 10
           repeat: true
           triggeredOnStart: true
           running: true
           onTriggered: process.start("/bin/cat", [ "/proc/uptime" ]);
       }
      

      it outputs:
      QProcess::start: Process is already running
      QProcess::start: Process is already running
      QProcess::start: Process is already running
      QProcess::start: Process is already running
      QProcess::start: Process is already running
      QProcess::start: Process is already running
      QProcess::start: Process is already running
      QProcess::start: Process is already running

      I think that the shell here is just "cat /proc/uptime", it should output some numbers.
      Maybe I should read and understand Qprocess class first?

      JonBJ 1 Reply Last reply
      0
      • L lxy12345

        @jsulm when I tried the code ,
        Text {
        id: text
        }

        Process{
            id: process
             onReadyRead: text.text = readAll();
        }
        Timer {
             interval: 10
             repeat: true
             triggeredOnStart: true
             running: true
             onTriggered: process.start("/bin/cat", [ "/proc/uptime" ]);
         }
        

        it outputs:
        QProcess::start: Process is already running
        QProcess::start: Process is already running
        QProcess::start: Process is already running
        QProcess::start: Process is already running
        QProcess::start: Process is already running
        QProcess::start: Process is already running
        QProcess::start: Process is already running
        QProcess::start: Process is already running

        I think that the shell here is just "cat /proc/uptime", it should output some numbers.
        Maybe I should read and understand Qprocess class first?

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #12

        @lxy12345
        I don't know anything about QML, but

        QProcess::start: Process is already running

        means that you have a QProcess instance where you have set of a start() but it has not yet completed and you have not waited for it, and now you're trying to set off a new start(). You either need to wait for completion of the process instance, or you need to use a new instance of QProcess each time. As I say, i don't know QML how to do that, but that's the cause/reason.

        1 Reply Last reply
        2
        • mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by
          #13

          Hi
          Since you set the timer to repeat, it will start a new QProcess each time and
          10 ms might be too short. try raising it so the other Qprocess gets change to finished.

          Timer {
          interval: 10
          repeat: true

          JonBJ 1 Reply Last reply
          0
          • mrjjM mrjj

            Hi
            Since you set the timer to repeat, it will start a new QProcess each time and
            10 ms might be too short. try raising it so the other Qprocess gets change to finished.

            Timer {
            interval: 10
            repeat: true

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #14

            @mrjj
            Really it ought have a handler for "process finished" signal, to be robust. I don't know how you do that from QML.

            OP might have a go at the naughty:

                 onTriggered: process.start("/bin/cat", [ "/proc/uptime" ]); process.waitForFinished();
            

            with all the caveats. I don't know if that would work simpler.

            mrjjM 1 Reply Last reply
            1
            • JonBJ JonB

              @mrjj
              Really it ought have a handler for "process finished" signal, to be robust. I don't know how you do that from QML.

              OP might have a go at the naughty:

                   onTriggered: process.start("/bin/cat", [ "/proc/uptime" ]); process.waitForFinished();
              

              with all the caveats. I don't know if that would work simpler.

              mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by
              #15

              @JonB
              Yes i agree as guessing on execution time is bound to fail in many other cases.

              L 1 Reply Last reply
              0
              • mrjjM mrjj

                @JonB
                Yes i agree as guessing on execution time is bound to fail in many other cases.

                L Offline
                L Offline
                lxy12345
                wrote on last edited by
                #16

                @mrjj finally, I found the reason. I should add console.log() to show output . The post is correct, thanks guys

                JonBJ 1 Reply Last reply
                1
                • L lxy12345

                  @mrjj finally, I found the reason. I should add console.log() to show output . The post is correct, thanks guys

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #17

                  @lxy12345 said in run a sh shell while clicking button in QML with QT5.15.0:

                  The post is correct

                  What post is correct?

                  L 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @lxy12345 said in run a sh shell while clicking button in QML with QT5.15.0:

                    The post is correct

                    What post is correct?

                    L Offline
                    L Offline
                    lxy12345
                    wrote on last edited by
                    #18

                    @JonB http://71.254.128.33/qml/process.html This post.

                    JonBJ 1 Reply Last reply
                    0
                    • L lxy12345

                      @JonB http://71.254.128.33/qml/process.html This post.

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #19

                      @lxy12345
                      Ah, I see. Yes, that looks reasonable. However, it has no code for waiting for the QProcess::finished signal. I admitted earlier I do not know how QML works with regard to instances. But if it does not create new QProcess instances, and if you re-use the one instance before the cat OS command has completed, you will get the QProcess::start: Process is already running error you showed earlier. Since the /bin/cat /proc/uptime completes "quickly" you may get away with it for a while.

                      You may well be using this as just an example to play with QProcess, I don't know. But be aware that if you are really trying to do /bin/cat /proc/uptime , that is a waste of time! All that does is an OS command to read the contents of the file. You would be better doing this by just opening the file /proc/uptime and reading its content from QML, without any QProcess OS command at all.

                      L 1 Reply Last reply
                      0
                      • JonBJ JonB

                        @lxy12345
                        Ah, I see. Yes, that looks reasonable. However, it has no code for waiting for the QProcess::finished signal. I admitted earlier I do not know how QML works with regard to instances. But if it does not create new QProcess instances, and if you re-use the one instance before the cat OS command has completed, you will get the QProcess::start: Process is already running error you showed earlier. Since the /bin/cat /proc/uptime completes "quickly" you may get away with it for a while.

                        You may well be using this as just an example to play with QProcess, I don't know. But be aware that if you are really trying to do /bin/cat /proc/uptime , that is a waste of time! All that does is an OS command to read the contents of the file. You would be better doing this by just opening the file /proc/uptime and reading its content from QML, without any QProcess OS command at all.

                        L Offline
                        L Offline
                        lxy12345
                        wrote on last edited by
                        #20

                        @JonB thanks for replying me. The "cat /proc/uptime" cmd is just an example. I change the cmd in my project, I use this code to open a shell which controls some peripherals.

                        1 Reply Last reply
                        0
                        • foxomanF Offline
                          foxomanF Offline
                          foxoman
                          wrote on last edited by foxoman
                          #21

                          Basically close/kill / terminate the process before running a new process
                          here an example I extracted from one of my projects as I keep "bash" process alive till closing the app itself.
                          so try to find where you wan to stop the process and close it.

                          cmd.h

                          #pragma once
                          #include <QProcess>
                          #include <QVariant>
                          
                          class Process : public QProcess
                          {
                              Q_OBJECT
                          public:
                              explicit Process( QObject* parent = Q_NULLPTR ) : QProcess( parent )
                              { }
                          
                               // If want to use Start with arguments
                              Q_INVOKABLE void start( const QString& program, const QVariantList& arguments )
                              {
                                  QStringList args;
                          
                                  // convert QVariantList from QML to QStringList for QProcess
                                  for ( const auto& temp : arguments ) {
                                      args << temp.toString();
                                  }
                          
                                  QProcess::setProcessChannelMode( QProcess::MergedChannels );
                                  QProcess::start( program, args );
                              }
                          
                              // If wan to start without arguments for Qt > 5.14
                              Q_INVOKABLE void start( const QString& program )
                              {
                          
                                  QProcess::setProcessChannelMode( QProcess::MergedChannels );
                                  QProcess::setProgram( program );
                                  QProcess::start();
                                  QProcess::open( QProcess::ReadWrite );
                              }
                          
                              Q_INVOKABLE QByteArray readAll() { return QProcess::readAll(); }
                              Q_INVOKABLE QByteArray readLine() { return QProcess::readLine(); }
                          
                               // if you want to write to an active process, not fully tested!
                              Q_INVOKABLE qint64 write( const QString& data )
                              {
                                  return QProcess::write( qPrintable( data ) );
                              }
                          
                          private:
                              Q_DISABLE_COPY( Process )
                          };
                          
                          

                          In main.h

                          qmlRegisterType<Process>( "Process", 1, 0, "Process" );
                          

                          In main.qml

                          import QtQuick 2.15
                          import QtQuick.Controls 2.15
                          import QtQuick.Layouts 1.15
                          import Qt.labs.platform 1.1
                          import Process 1.0
                          
                          ApplicationWindow {
                              visible: true
                              width: 640
                              height: 480
                              title: qsTr("Hello World")
                          
                              Component.onCompleted: {
                                  py.start("bash")
                              }
                          
                              // use py.close() or py.kill(0 or py.terminate() to kill the process
                              Component.onDestruction: py.close()
                          
                              Process {
                                  id: py
                          
                                  property string output: ""
                          
                                  onStarted: print("Started")
                                  onFinished: print("Closed")
                          
                                  onErrorOccurred: console.log("Error Ocuured: ", error)
                          
                                  onReadyReadStandardOutput: {
                                      output = py.readAll()
                                      term.text += output
                                  }
                              }
                          
                              Page {
                          
                                  anchors.fill: parent
                          
                                  ScrollView {
                                      id: view
                                      anchors.fill: parent
                          
                                      TextArea {
                                          id: term
                                          textFormat: TextArea.RichText
                                      }
                                  }
                          
                                  footer: RowLayout {
                                      Layout.fillWidth: true
                          
                                      TextField {
                                          id: input
                                          Layout.fillWidth: true
                                      }
                                      Button {
                                          text: "Send!"
                                          property string command: input.text.trim() + "\n"
                                          onClicked: {
                                              py.write(command)
                                              term.text += ("<br /><b>" + command + " : </b>")
                                          }
                                      }
                                  }
                              }
                          }
                          
                          

                          Test Qml Bash App

                          I have run cat /proc/uptime as one program command.

                          Tech Addict, Ubuntu Gnu/Linux Fan and Qt/C++ Developer. || https://www.foxoman.net/

                          1 Reply Last reply
                          1
                          • foxomanF Offline
                            foxomanF Offline
                            foxoman
                            wrote on last edited by
                            #22

                            Here is an update to run multiple process as a replay to reddit QA

                            import QtQuick 2.15
                            import QtQuick.Controls 2.15
                            import Process 1.0
                            
                            ApplicationWindow {
                                visible: true
                                width: 640
                                height: 480
                                title: "Run a sh file in CMD!"
                            
                                // prcoess to run and read .sh file
                                Process {
                                    id: cmd
                            
                                    property string output: ""
                            
                                    onStarted: print("Started")
                            
                                    // Once reading the .sh finish we will run another process to run the notify-send!
                                    onFinished: notify.start("notify-send",
                                                             ["-t", "4000", "Reading .sh file Completed!"])
                            
                                    onErrorOccurred: console.log("Error Ocuured: ", error)
                            
                                    onReadyReadStandardOutput: {
                                        output = cmd.readAll()
                                        txt.text += output
                                    }
                                }
                            
                                // process to run firefox
                                Process {
                                    id: fireFox
                            
                                    property string output: ""
                            
                                    // start notify process once we run firefox!
                                    onStarted: notify.start("notify-send",
                                                            ["-t", "4000", "Starting FireFox!"])
                                    onFinished: print("Closed")
                            
                                    onErrorOccurred: console.log("Error Ocuured: ", error)
                            
                                    onReadyReadStandardOutput: {
                                        output = cmd.readAll()
                                        console.log("READING CONSOLE: ", output)
                                    }
                                }
                            
                                // process to run notify-osd !!
                                Process {
                                    id: notify
                            
                                    property string output: ""
                            
                                    onStarted: print("Started")
                                    onFinished: print("Closed")
                            
                                    onErrorOccurred: console.log("Error Ocuured: ", error)
                            
                                    onReadyReadStandardOutput: {
                                        output = cmd.readAll()
                                        console.log("READING CONSOLE: ", output)
                                    }
                                }
                            
                                Column {
                                    anchors.centerIn: parent
                                    TextArea {
                                        id: txt
                                        text: ""
                                    }
                            
                                    Row {
                                        Button {
                                            text: "Run SH!"
                                            onClicked: cmd.start("/home/foxoman/file.sh")
                                        }
                                        Button {
                                            text: "Run FireFox!"
                                            onClicked: fireFox.start("firefox")
                                        }
                                        Button {
                                            text: "Run Notify"
                                            onClicked: notify.start(
                                                           "notify-send",
                                                           ["-t", "4000", "OSD Notify From Command Line!"])
                                        }
                                    }
                                }
                            }
                            
                            
                            

                            Tech Addict, Ubuntu Gnu/Linux Fan and Qt/C++ Developer. || https://www.foxoman.net/

                            1 Reply Last reply
                            1

                            • Login

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved