Results 1 to 3 of 3

Thread: Using QProcess on 7zip and connecting Slots does not provide output to Textbox Widget

  1. #1
    Join Date
    May 2019
    Posts
    2
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Using QProcess on 7zip and connecting Slots does not provide output to Textbox Widget

    I started using Qt5 about a week or so ago. I've been using C# for about 4 years and the transition to C++ and Qt has been mostly painless. As practice I'm porting a C# program to C++ and Qt. One of the things my C# program does is allows the drag and drop of file names into a list box. I can then select the Archive type and tell it to process the list into archives. Directories get all their files put into an Archive, files get compressed on their own. I've got this working in both Windows and Linux without issue.

    Now for my issue,

    I was using a progress bar that updated after every line was Archived. Now I want a progress bar that updates based on the current archives status. My final goal will be to parse the output and create a progress bar that updates based on the percent complete reported, but I'm stuck. I can't get the stout from the 7z application until it finishes it's process. I need to get it while it's processing. I've been hitting google, stack, here, and the Qt documentation and I just can't figure it out. I found one post >here< that solved the issue, but it wasn't clear on how it completed the task.

    I've tried to strip out as much code as possible in my post example. I left the check boxes and list control references in for clarity on what's happening. What happens is, the button on_cmdArchiveAs_clicked is pressed. This disables the button and starts a sort of event loop named ArchiveFirstListItems. The first part of the loop connects to the process, then after the process is complete it triggers the process again, until the list widget is empty. Doing it this way allows adding items to the process list while the process is underway.

    Qt Code:
    1. static QProcess* process = new QProcess();
    2.  
    3. void MainWindow::on_cmdArchiveAs_clicked()
    4. {
    5. ui->cmdArchiveAs->setEnabled(false);
    6. ArchiveFirstListItems();
    7. }
    8.  
    9. void MainWindow::ArchiveFirstListItems()
    10. {
    11. if(ui->lstFiles->count()>0)
    12. {
    13. QString ArchiveType;
    14. QString NewEXT;
    15. if (ui->optZip->isChecked())
    16. {
    17. ArchiveType = "zip";
    18. NewEXT = "zip";
    19. }
    20. else if (ui->opt7Zip->isChecked())
    21. {
    22. ArchiveType = "7z";
    23. NewEXT = "7z";
    24. }
    25. else if (ui->optCbz->isChecked())
    26. {
    27. ArchiveType = "zip";
    28. NewEXT = "cbz";
    29. }
    30. QFileInfo CurrentFile(ui->lstFiles->item(0)->text());
    31. process = new QProcess(this);
    32.  
    33. //process->setReadChannel(QProcess::StandardOutput);
    34. //process->setProcessChannelMode(QProcess::MergedChannels);
    35. //process->setProcessChannelMode(QProcess::ForwardedChannels);
    36.  
    37. QObject::connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput()));
    38. QObject::connect(process, SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError()));
    39.  
    40. //QObject::connect( process, &QProcess::readyReadStandardOutput, this, &MainWindow::readyReadStandardOutput );
    41. //QObject::connect( process, &QProcess::readyReadStandardError, this, &MainWindow::readyReadStandardError );
    42.  
    43. QObject::connect(process, SIGNAL(finished(int)), this, SLOT(processFinished()));
    44. process->setProgram("7z");
    45. Args << "a";
    46. if (ArchiveType == "7z")
    47. {
    48. Args << "-t7z";
    49. Args << "-m0=LZMA2:d512m:fb273";
    50. Args << "-mx9";
    51. Args << "-myx=9";
    52. Args << "-mtc=off";
    53. Args << "-mtm=off";
    54. }
    55. else
    56. {
    57. Args << "-tzip";
    58. Args << "-mx";
    59. Args << "-mtc=off";
    60. }
    61. if(ui->chkDeleteOriginalFilesOnSuccess->isChecked())
    62. {
    63. Args << "-sdel";
    64. }
    65. Args << """" + CurrentFile.filePath() + "." + NewEXT + """" ;
    66. if(CurrentFile.isDir()){
    67. if(ui->chkAddInfoFileDirOnly->isChecked())
    68. {
    69. QFile file(ui->lstFiles->item(0)->text() + "/info.txt");
    70. if (file.open(QIODevice::ReadWrite))
    71. {
    72. QTextStream stream(&file);
    73. stream << CurrentFile.fileName() << endl;
    74. }
    75. }
    76. Args << """" + ui->lstFiles->item(0)->text() + "/*""";
    77. }
    78. else
    79. {
    80. Args << """" + ui->lstFiles->item(0)->text() + """";
    81. }
    82. qDebug() << Args;
    83. process->setArguments(Args);
    84. ui->lstFiles->takeItem(0);
    85. process->start();
    86. }
    87. else
    88. {
    89. ui->cmdArchiveAs->setEnabled(true);
    90. }
    91. }
    92.  
    93. void MainWindow::readyReadStandardOutput()
    94. {
    95. ui->txtOutput->appendPlainText(process->readAllStandardOutput());
    96. //qDebug()<<process->readAllStandardOutput();
    97. //QObject::disconnect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(readyReadStandardOutput()));
    98. }
    99.  
    100. void MainWindow::readyReadStandardError()
    101. {
    102. ui->txtOutput->appendPlainText(process->readAllStandardError());
    103. //qDebug()<<process->readAllStandardError();
    104. //QObject::disconnect(process, SIGNAL(readyReadStandardError()), this, SLOT(readyReadStandardError()));
    105. }
    106.  
    107. void MainWindow::processFinished()
    108. {
    109. ArchiveFirstListItems();
    110. }
    To copy to clipboard, switch view to plain text mode 

    What I've Tried;
    I tried to output to qDebug as well as the textbox.
    I've tried to set the read channel to StandardOutput and StandardError.
    I've tried setting the setProcessChannelMode to MergedChannels and ForwardedChannels.
    I've compiled it in both Windows and Linux.

    Topics I've read;
    qprocess

    I can provide the source files if it will help. I can also create a test package instead with just the source, however I'm new to Qt and C++ so it may take some time.

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Using QProcess on 7zip and connecting Slots does not provide output to Textbox Wi

    Have you checked if the 7z program writes to its stdout and/or stderr when being called from a shell?

    E.g. something like

    $> 7z ...... > out.txt &
    $> less -f out.txt

    I.e. does "less" get new input from the file while the archiver is running?

    Maybe also experiement with the "-bs" option.

    Cheers,
    _

  3. The following user says thank you to anda_skoa for this useful post:

    kayot (29th May 2019)

  4. #3
    Join Date
    May 2019
    Posts
    2
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Using QProcess on 7zip and connecting Slots does not provide output to Textbox Wi

    The issue was -bs, I thought it defaulted to o1, e2, p1 but that isn't the case when it's ran from a C++ instance. I had to tell it to put progress or -bsp# to 1. To direct quote the manual for 7zip 18.06 (x64);

    -bs (Set output stream for output/error/progress line) switch

    Syntax
    -bs{o|e|p}{0|1|2}
    {id} Stream Type
    o standard output messages
    e error messages
    p progress information
    {N} Stream Destination
    0 disable stream
    1 redirect to stdout stream
    2 redirect to stderr stream
    Default values: o1, e2, p1.

    Examples
    7z t a.7z -bse1 > messages.txt
    tests a.7z archive and sends error messages to stdout that is redirected to messages.txt

    7z a -si -so -bsp2 -txz -an < file.tar > file.tar.xz
    compresses file.tar (from stdin) to file.tar.xz (stdout stream) and shows progress information in stderr stream that can be seen at console window.

    Commands that can be used with this switch
    a (Add), d (Delete), h (Hash), l (List), e (Extract), u (Update), x (Extract with full paths)
    I was able to use the Windows Subsystem for Linux to speed testing up in this case. When I sent stdout to a text file with > FileName.txt and used less, I saw that without -bsp1 it wasn't outputting anything. When the process finished I had the same thing I had in my Qt application. Adding -bsp1 to the 7zip command;

    Qt Code:
    1. if (ArchiveType == "7z")
    2. {
    3. Args << "-t7z";
    4. Args << "-bsp1"; //<== Added Here
    5. Args << "-m0=LZMA2:d512m:fb273";
    6. Args << "-mx9";
    7. Args << "-myx=9";
    8. Args << "-mtc=off";
    9. Args << "-mtm=off";
    10. }
    11. else
    12. {
    13. Args << "-tzip";
    14. Args << "-bsp1"; //<== And Here
    15. Args << "-mx";
    16. Args << "-mtc=off";
    17. }
    To copy to clipboard, switch view to plain text mode 

    I got full feedback. I can also send the output to a different channel, -bsp2 which will send it to the error channel for easier parsing. I can use the output channel for final details and each line is absolutely positioned.

    In short, my connect was working fine. It was 7zip that was giving me trouble.

Similar Threads

  1. Connecting many SIGNALS to SLOTS
    By Alex22 in forum Qt Programming
    Replies: 3
    Last Post: 2nd December 2015, 10:31
  2. Connecting QML signals with Qt slots
    By KIBSOFT in forum Qt Quick
    Replies: 1
    Last Post: 15th November 2010, 10:18
  3. Connecting signals and slots help pls
    By bod in forum Qt Programming
    Replies: 9
    Last Post: 1st July 2008, 16:01
  4. Connecting to Undeclared Slots
    By Dumbledore in forum Qt Tools
    Replies: 5
    Last Post: 11th October 2007, 18:19
  5. Replies: 1
    Last Post: 7th August 2007, 09:27

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.