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.