Вызов setupUi() создает и компонует все виджеты форм, устанавливает соединения сигнал—слот для слотов on_objectName_signalName() и связывает кнопку Quit (выйти) с функцией QDialog::accept(). После этого мы вручную связываем три сигнала объекта QProcess с тремя закрытыми слотами. Любые сообщения внешнего процесса для потока cerr мы будем обрабатывать в функции updateOutputTextEdit().
01 void ConvertDialog::on_browseButton_clicked()
02 {
03 QString initialName = sourceFileEdit->text();
04 if (initialName.isEmpty())
05 initialName = QDir::homePath();
06 QString fileName = QFileDialog::getOpenFileName(this,
07 tr("Choose File"), initialName);
08 fileName = QDir::convertSeparators(fileName);
09 if (!fileName.isEmpty()) {
10 sourceFileEdit->setText(fileName);
11 convertButton->setEnabled(true);
12 }
13 }
Сигнал clicked() кнопки Browse (просмотреть) автоматически связывается в функции setupUi() со слотом on_browseButton_clicked(). Если пользователь ранее выбирал какой-нибудь файл, мы инициализируем диалоговое окно выбора файла именем этого файла; в противном случае мы используем домашний каталог пользователя.
01 void ConvertDialog::on_convertButton_clicked()
02 {
03 QString sourceFile = sourceFileEdit->text();
04 targetFile = QFileInfo(sourceFile).path()
05 + QDir::separator() + QFileInfo(sourceFile).baseName()
06 + "." + targetFormatComboBox->currentText().toLower();
07 convertButton->setEnabled(false);
08 outputTextEdit->clear();
09 QStringList args;
10 if (enhanceCheckBox->isChecked())
11 args << "-enhance";
12 if (monochromeCheckBox->isChecked())
13 args << "-monochrome";
14 args << sourceFile << targetFile;
15 process.start("convert", args);
16 }
Когда пользователь нажимает кнопку Convert (преобразовать), мы копируем имя исходного файла и изменяем его расширение в соответствии с новым форматом файла. Мы используем зависимый от платформы разделитель каталогов ('/' или '\' возвращается функцией QDir::separator()) вместо жесткого кодирования этих символов, поскольку пользователь будет видеть имя файла.
Затем отключаем кнопку Convert, чтобы пользователь не мог случайно запустить одновременно несколько процессов преобразования, и очищаем поле текстового редактора, используемое нами для отображения информации о состоянии.
Для инициирования внешнего процесса мы вызываем функцию QProcess::start() с именем программы, которая должна выполняться (convert), и всеми ее аргументами. В данном случае мы передаем флажки -enhance и -monochrome, если пользователь выбрал соответствующие опции, и затем имена исходного и целевого файлов. Тип выполняемого преобразования программа convert определяет по расширениям файлов.
01 void ConvertDialog::updateOutputTextEdit()
02 {
03 QByteArray newData = process.readAllStandardError();
04 QString text = outputTextEdit->toPlainText()
05 + QString::fromLocal8Bit(newData);
06 outputTextEdit->setPlainText(text);
07 }
При всякой записи внешним процессом в поток cerr вызывается слот updateOutputTextEdit(). Мы считываем текст сообщения об ошибке и добавляем его в существующий текст QTextEdit.
01 void ConvertDialog::processFinished(int exitCode,
02 QProcess::ExitStatus exitStatus)
03 {
04 if (exitStatus == QProcess::CrashExit) {
05 outputTextEdit->append(tr("Conversion program crashed"));
06 } else if (exitCode != 0) {
07 outputTextEdit->append(tr("Conversion failed"));
08 } else {
09 outputTextEdit->append(tr("File %1 created").arg(targetFile));
10 }
11 convertButton->setEnabled(true);
12 }
По окончании процесса мы уведомляем пользователя о результате и включаем кнопку Convert.
01 void ConvertDialog::processError(QProcess::ProcessError error)
02 {
03 if (error == QProcess::FailedToStart) {
04 outputTextEdit->append(tr("Conversion program not found"));
05 convertButton->setEnabled(true);
06 }
07 }
Если процесс не удается запустить, QProcess генерирует сигнал error() вместо finished(). Мы выдаем сообщение об ошибке и включаем кнопку Convert.
В этом примере преобразования файлов выполнялись асинхронно, т.е. QProcess запускал программу convert и сразу же возвращал управление приложению. Это сохраняет работоспособность пользовательского интерфейса во время выполнения преобразований в фоновом режиме. Но в некоторых ситуациях необходимо, чтобы внешний процесс завершился, и только после этого мы сможем идти дальше в нашем приложении; в таких случаях требуется синхронная работа QProcess.