//============================================================================= // // File : KvsObject_process.cpp // Creation date : Fri Mar 18 21:30:48 CEST 2005 // by Tonino Imbesi(Grifisx) and Alessandro Carbone(Noldor) // // This file is part of the KVIrc irc client distribution // Copyright (C) 2005-2008 Alessandro Carbone (elfonol at gmail dot com) // // This program is FREE software. You can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your opinion) any later version. // // This program is distributed in the HOPE that it will be USEFUL, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, write to the Free Software Foundation, // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //============================================================================= #include "KvsObject_process.h" #include "KviError.h" #include "kvi_debug.h" #include "kvi_settings.h" #include "KviLocale.h" #include "QProcess" /* @doc: process @keyterms: process object class, process @title: process class @type: class @short: A class to manage process. @inherits: [class]object[/class] @description: The Process class is used to start external programs and to communicate with them.[br] !WARNING AT LAST YOU HAVE TO CLOSE THE PROCESS! @functions: !fn: $addArgument() With this command you give the process name (or more arguments) for comunication. Es: see the next example. !fn: $startProcess() Tries to run the process.[br] Es: [br] %process=$new(process);[br] %process->$addArg("cmd.exe");[br] %process->$start();[br] !fn: $readStdout() Reads the data that the process has written to standard output. !fn: $readStderr() Reads the data that the process has written to standard error. Es:[br] -------------------Start:[br] class (test,object)[br] {[br] slotReadStdout()[br] {[br] %stdo = %Process->$readStdout()[br] #%Aoutput->$append(%stdo);// coming soon in the new texteditor class[br] %Aoutput->$settext(%stdo);[br] }[br] slotReadStderr()[br] {[br] %stderr= %Process->$readStderr()[br] #%Aoutput->$append(%stderr);// coming soon in the new texteditor class[br] %Aoutput->$settext(%stderr);[br] }[br] }[br] %tt=$new(test)[br] %A=$new(widget)[br] %A->$setGeometry(100,100,400,300)[br] %layoutA=$new(layout,%A)[br] %Ainput=$new(lineedit,%A)[br] #%Aoutput=$new(textedit,%A)// coming soon in the new texteditor class[br] %Aoutput=$new(label,%A)[br] %bclosekill=$new(button,%A)[br] %bclosekill->$settext("&CloseKill ")[br] %bkill=$new(button,%A)[br] %bkill->$settext("&Kill ")[br] %bterminate=$new(button,%A)[br] %bterminate->$settext("&Ask to Terminate ")[br] %layoutA->$addwidget(%Ainput,0,0)[br] %layoutA->$addwidget(%Aoutput,1,0)[br] %layoutA->$addwidget(%bclosekill,3,0)[br] %layoutA->$addwidget(%bkill,4,0,)[br] %layoutA->$addwidget(%bterminate,5,0)[br] %Process=$new(process)[br] %Process->$addArgument("cmd.exe")[br] %Process->$startProcess();[br] connect %Process readyReadStdout %tt slotReadStdout[br] connect %Process readyReadStderr %tt slotReadStderr[br] privateimpl(%Ainput,returnPressedEvent)[br] { %command=%Ainput->$text() "\r\n"[br] %Process->$writeToStdin(%command);[br] %Ainput->$setText("");[br] }[br] privateimpl(%bclosekill,mousepressevent)[br] {[br] %Process->$closekill();[br] delete %A;[br] }[br] privateimpl(%bkill,mousepressevent)[br] {[br] %Process->$kill();[br] delete %A;[br] }[br] privateimpl(%bterminate,mousepressevent)[br] {[br] %Process->$tryTerminate();[br] delete %A;[br] }[br] %A->$show();[br] --------------------End.[br] !fn: $writeToStdin() Whit this command you send a command to the process: !fn: $closekill() This tries to terminate the process the nice way.[br] If the process is still running after 5 seconds, it terminates the process the hard way.[br] (I think that this is the better way.)[br] Es: %Process->close_kill(); !fn: $kill() Kill the process in hard way.(Bad Idea) !fn: $tryTerminate() Tries to terminate the process.(It could be well but...) !fn: $closeStdin() Close the standard Input. !fn: $isRunning() Return 1 if the process is running, else return 0. !fn: $normalExit() Returns TRUE if the process has exited normally; otherwise returns FALSE. !fn: $readyReadStdoutEvent() This function is invoched by the process when there are new datas.[br] The default implementation emits the [classfnc]$readyReadStdout[/classfnc]() signal. !fn: $readyReadStderrEvent() This function is invoched by the process when there are new error messages.[br] The default implementation emits the [classfnc]$readyReadStderr[/classfnc]() signal. @signals: !sg: $readyReadStdout() This signal is emitted by the default implementation of [classfnc]$readyReadStdoutEvent[/classfnc]().[br] If you reimplement that function you will have to emit the signal manually (if you still need it). !sg: $readyReadStderr() This signal is emitted by the default implementation of [classfnc]$readyReadStderrEvent[/classfnc](). */ KVSO_BEGIN_REGISTERCLASS(KvsObject_process,"process","object") KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,addArgument); KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,startProcess); KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,readStdout); KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,readStderr); KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,writeToStdin); KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,closekill); KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,kill); KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,tryTerminate); KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,closeStdin); KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,isRunning); KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,normalExit); // Events KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,readyReadStdoutEvent); KVSO_REGISTER_HANDLER_BY_NAME(KvsObject_process,readyReadStderrEvent); KVSO_END_REGISTERCLASS(KvsObject_process) KVSO_BEGIN_CONSTRUCTOR(KvsObject_process,KviKvsObject) m_pProcess = new QProcess(); connect(m_pProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(slotReadStdout())); connect(m_pProcess,SIGNAL(readyReadStandardError()),this,SLOT(slotReadStderr())); KVSO_END_CONSTRUCTOR(KvsObject_process) KVSO_BEGIN_DESTRUCTOR(KvsObject_process) delete m_pProcess; KVSO_END_CONSTRUCTOR(KvsObject_process) KVSO_CLASS_FUNCTION(process,addArgument) { QString szArgument; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("argument",KVS_PT_NONEMPTYSTRING,0,szArgument) KVSO_PARAMETERS_END(c) m_szArgs.append(szArgument); return true; } //->Start the process. KVSO_CLASS_FUNCTION(process,startProcess) { CHECK_INTERNAL_POINTER(m_pProcess) QString szcmd; szcmd = m_szArgs.takeFirst(); m_pProcess->start(szcmd, m_szArgs); if(m_pProcess->state()==QProcess::NotRunning) { c->warning( __tr2qs_ctx("Process could not be started.","objects")); } return true; } //-->Read the standard output. KVSO_CLASS_FUNCTION(process,readStderr) { CHECK_INTERNAL_POINTER(m_pProcess) QString ng_Process = m_pProcess->readAllStandardError(); c->returnValue()->setString(ng_Process); return true; } //-->Read the standard error. KVSO_CLASS_FUNCTION(process,readStdout) { CHECK_INTERNAL_POINTER(m_pProcess) QString ng_Process =m_pProcess->readAllStandardOutput(); c->returnValue()->setString(ng_Process); return true; } //-->Signals and slot to manage reading output and error from the process. KVSO_CLASS_FUNCTION(process,readyReadStdoutEvent) { emitSignal("readyReadStdout",c); return true; } KVSO_CLASS_FUNCTION(process,readyReadStderrEvent) { emitSignal("readyReadStderr",c); return true; } KVSO_CLASS_FUNCTION(process,writeToStdin) { CHECK_INTERNAL_POINTER(m_pProcess) QString szCommand; KVSO_PARAMETERS_BEGIN(c) KVSO_PARAMETER("command",KVS_PT_STRING,0,szCommand) KVSO_PARAMETERS_END(c) if (m_pProcess) m_pProcess->write(szCommand.toUtf8().data()); return true; } //-->The 3 Closing process functions KVSO_CLASS_FUNCTION(process,closekill) { CHECK_INTERNAL_POINTER(m_pProcess) //I try to to terminate the process the nice way.... m_pProcess->terminate(); //If the process is still running after 5 seconds, I'll terminate the process in the hard way. QTimer::singleShot( 5000, m_pProcess, SLOT( kill() ) ); return true; } KVSO_CLASS_FUNCTION(process,kill) { CHECK_INTERNAL_POINTER(m_pProcess) m_pProcess->kill(); return true; } KVSO_CLASS_FUNCTION(process,tryTerminate) { CHECK_INTERNAL_POINTER(m_pProcess) m_pProcess->terminate(); return true; } //-->Close the standard input. KVSO_CLASS_FUNCTION(process,closeStdin) { CHECK_INTERNAL_POINTER(m_pProcess) m_pProcess->closeReadChannel(QProcess::StandardOutput); return true; } //->Returns if the process still runnig KVSO_CLASS_FUNCTION(process,isRunning) { CHECK_INTERNAL_POINTER(m_pProcess) c->returnValue()->setBoolean(m_pProcess->state()==QProcess::Running); return true; } //->Returns if the process exited. KVSO_CLASS_FUNCTION(process,normalExit) { CHECK_INTERNAL_POINTER(m_pProcess) c->returnValue()->setBoolean(m_pProcess->state()==QProcess::NotRunning && m_pProcess->exitStatus()==QProcess::NormalExit); return true; } void KvsObject_process::slotReadStdout() { KviKvsVariantList *params=0; callFunction(this,"readyReadStdoutEvent",params); } void KvsObject_process::slotReadStderr() { KviKvsVariantList *params=0; callFunction(this,"readyReadStderrEvent",params); } #ifndef COMPILE_USE_STANDALONE_MOC_SOURCES #include "m_KvsObject_process.moc" #endif //!COMPILE_USE_STANDALONE_MOC_SOURCES