File indexing completed on 2024-05-19 04:56:01
0001 /** 0002 * \file externalprocess.cpp 0003 * Handler for external process. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 22 Feb 2007 0008 * 0009 * Copyright (C) 2007-2018 Urs Fleisch 0010 * 0011 * This file is part of Kid3. 0012 * 0013 * Kid3 is free software; you can redistribute it and/or modify 0014 * it under the terms of the GNU General Public License as published by 0015 * the Free Software Foundation; either version 2 of the License, or 0016 * (at your option) any later version. 0017 * 0018 * Kid3 is distributed in the hope that it will be useful, 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0021 * GNU General Public License for more details. 0022 * 0023 * You should have received a copy of the GNU General Public License 0024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0025 */ 0026 0027 #include "externalprocess.h" 0028 #include <QProcess> 0029 #include <QString> 0030 #include <QStringList> 0031 #include "taggedfile.h" 0032 #include "iusercommandprocessor.h" 0033 #include "kid3application.h" 0034 0035 /** 0036 * Destructor. 0037 */ 0038 ExternalProcess::IOutputViewer::~IOutputViewer() 0039 { 0040 } 0041 0042 0043 /** 0044 * Constructor. 0045 * 0046 * @param app application context 0047 * @param parent parent object 0048 */ 0049 ExternalProcess::ExternalProcess(Kid3Application* app, QObject* parent) 0050 : QObject(parent), 0051 m_app(app), m_process(nullptr), m_outputViewer(nullptr) 0052 { 0053 setObjectName(QLatin1String("ExternalProcess")); 0054 const auto userCommandProcessors = m_app->getUserCommandProcessors(); 0055 for (IUserCommandProcessor* userCommandProcessor : userCommandProcessors) { 0056 userCommandProcessor->initialize(m_app); 0057 connect(userCommandProcessor->qobject(), SIGNAL(commandOutput(QString)), // clazy:exclude=old-style-connect 0058 this, SLOT(showOutputLine(QString))); 0059 } 0060 } 0061 0062 /** 0063 * Destructor. 0064 */ 0065 ExternalProcess::~ExternalProcess() 0066 { 0067 const auto userCommandProcessors = m_app->getUserCommandProcessors(); 0068 for (IUserCommandProcessor* userCommandProcessor : userCommandProcessors) { 0069 userCommandProcessor->cleanup(); 0070 } 0071 } 0072 0073 /** 0074 * Launch a command. 0075 * 0076 * @param name display name 0077 * @param args command and arguments 0078 * @param showOutput true to show output of process 0079 * @return false if process could not be executed. 0080 */ 0081 bool ExternalProcess::launchCommand(const QString& name, const QStringList& args, 0082 bool showOutput) 0083 { 0084 if (args.isEmpty()) 0085 return true; 0086 0087 if (!m_process) { 0088 m_process = new QProcess(parent()); 0089 } 0090 if (m_process->state() != QProcess::NotRunning) { 0091 m_process = new QProcess(parent()); 0092 } 0093 connect(m_process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>( 0094 &QProcess::finished), 0095 this, &ExternalProcess::finished, Qt::UniqueConnection); 0096 0097 if (showOutput && m_outputViewer) { 0098 m_process->setProcessChannelMode(QProcess::MergedChannels); 0099 connect(m_process, &QProcess::readyReadStandardOutput, 0100 this, &ExternalProcess::readFromStdout); 0101 m_outputViewer->setCaption(name); 0102 m_outputViewer->scrollToBottom(); 0103 } else { 0104 disconnect(m_process, &QProcess::readyReadStandardOutput, 0105 this, &ExternalProcess::readFromStdout); 0106 } 0107 0108 QStringList arguments = args; 0109 QString program = arguments.takeFirst(); 0110 if (program.startsWith(QLatin1Char('@'))) { 0111 program = program.mid(1); 0112 const auto userCommandProcessors = m_app->getUserCommandProcessors(); 0113 for (IUserCommandProcessor* userCommandProcessor : userCommandProcessors) { 0114 if (userCommandProcessor->userCommandKeys().contains(program)) { 0115 connect(userCommandProcessor->qobject(), SIGNAL(finished(int)), 0116 this, SIGNAL(finished(int)), Qt::UniqueConnection); 0117 if (userCommandProcessor->startUserCommand(program, arguments, 0118 showOutput)) { 0119 return true; 0120 } 0121 } 0122 } 0123 } 0124 m_process->start(program, arguments); 0125 if (!m_process->waitForStarted(10000)) { 0126 return false; 0127 } 0128 return true; 0129 } 0130 0131 /** 0132 * Read data from standard output and display it in the output viewer. 0133 */ 0134 void ExternalProcess::readFromStdout() 0135 { 0136 if (m_outputViewer) { 0137 m_outputViewer->append(QString::fromLocal8Bit( 0138 m_process->readAllStandardOutput())); 0139 } 0140 } 0141 0142 /** 0143 * Show a line in the output viewer. 0144 * @param msg message to be displayed 0145 */ 0146 void ExternalProcess::showOutputLine(const QString& msg) 0147 { 0148 if (m_outputViewer) { 0149 m_outputViewer->append(msg + QLatin1Char('\n')); 0150 } 0151 }