1 /*************************************************************************** 2 rcommand.h - description 3 ------------------- 4 begin : Mon Nov 11 2002 5 copyright : (C) 2002, 2006, 2007, 2009, 2010, 2013 by Thomas Friedrichsmeier 6 email : thomas.friedrichsmeier@kdemail.net 7 ***************************************************************************/ 8 9 /*************************************************************************** 10 * * 11 * This program is free software; you can redistribute it and/or modify * 12 * it under the terms of the GNU General Public License as published by * 13 * the Free Software Foundation; either version 2 of the License, or * 14 * (at your option) any later version. * 15 * * 16 ***************************************************************************/ 17 18 #ifndef RCOMMAND_H 19 #define RCOMMAND_H 20 21 #include <QString> 22 #include <QObject> 23 #include <QList> 24 25 #include "rdata.h" 26 27 #define MAX_RECEIVERS_PER_RCOMMAND 3 28 29 class RCommandReceiver; 30 class RCommand; 31 class RCommandProxy; 32 33 /** R Commands can be arranged in a simple chain to make sure they are not interrupted by other commands. 34 * Also, command may need to run sub-commands. 35 @see \ref UsingTheInterfaceToR 36 @see RInterface::startChain 37 @see RInterface::closeChain */ 38 class RCommandChain { 39 public: isClosed()40 bool isClosed () const { return closed; }; 41 /** @returns true, if there are no sub-commands or sub-chains waiting in this chain */ isEmpty()42 bool isEmpty () const { return sub_commands.isEmpty (); }; isCommand()43 bool isCommand () const { return is_command; }; parentChain()44 RCommandChain* parentChain () const { return parent; }; 45 RCommand *toCommand (); 46 protected: 47 friend class RCommandStack; 48 friend class RCommandStackModel; 49 RCommandChain (bool is_chain=true) : closed (!is_chain), is_command (!is_chain) {}; 50 QList<RCommandChain*> sub_commands; 51 bool closed; 52 bool is_command; 53 RCommandChain *parent; 54 }; 55 56 /** this struct is used to store the R output to an RCommand. The RCommand basically keeps a list of ROutputString (s). The difference to a normal 57 QString is, that additionally we store information on whether the output was "normal", "warning", or an "error". */ 58 struct ROutput { 59 enum ROutputType { 60 NoOutput, /**< No output. Rarely used. */ 61 Output, /**< normal output */ 62 Warning, /**< R warning */ 63 Error /**< R error */ 64 }; 65 ROutputType type; 66 QString output; 67 }; 68 69 typedef QList<ROutput*> ROutputList; 70 71 /** Supplies signals for RCommands. 72 * Obtain an instance of this using RCommand::notifier (); 73 * Currently, only a single signal is available: When the command has finished. Further signals may be added, in the future. 74 * 75 * @Note You can also use this in connection with RCommandReceiver-based classes, if interested in RCommandReceiver::cancelOutstandingCommands(). 76 */ 77 class RCommandNotifier : public QObject { 78 Q_OBJECT 79 signals: 80 void commandFinished (RCommand *command); 81 private: 82 friend class RCommand; 83 RCommandNotifier (); 84 ~RCommandNotifier (); emitFinished(RCommand * command)85 void emitFinished (RCommand *command) { emit commandFinished (command); }; 86 }; 87 88 /** For introductory information on using RCommand, see \ref UsingTheInterfaceToR 89 90 This class is used to encapsulate an R-command, so it can be easily identified 91 in a chain of commands. It is needed, since communication with R is asynchronous 92 and it is therefore not possible to get the result of an R-call right away. 93 Instead, create an object of this class, specifying the RCommandReceiver that should 94 be called when the command has finished. You can then retrieve all information 95 on the command (including the reply) from the object that is passed to your handler. 96 97 There are several ways to identify a command when it's finished (needed, if a single RCommandReceiver needs to handle the results of 98 several different commands): 99 - storing the id () (each command is automatically assigned a unique id, TODO: do we need this functionality? Maybe remove it for redundancy) 100 - passing appropriate flags to know how to handle the command 101 - keeping the pointer (CAUTION: don't use that pointer except to compare it with the pointer of an incoming command. Commands get deleted when they are finished, and maybe (in the future) if they become obsolete etc. Hence the pointers you keep may be invalid!) 102 (- checking the command-string) 103 Note that an RCommand carries a whole lot of information around. However, RCommands generally don't get 104 kept around very long, so they should not be a memory issue. 105 *@author Thomas Friedrichsmeier 106 */ 107 class RCommand : public RData, public RCommandChain { 108 public: 109 /** constructs an RCommand. 110 @param command The command (string) to be run in the backend. This may include newlines and ";". The command should be a complete statement. If it is an incomplete statement, the backend will not wait for the rest of the command to come in, but rather the command will fail with RCommand::errorIncomplete. 111 @param type An integer being the result of a bit-wise OR combination of the values in RCommand::CommandTypes. The type-parameter is used to indicate the type of command, and also how the command should retrieve information (as a usual string, or as a data vector). See \ref RCommand::CommandTypes 112 @param rk_equiv Not yet used: a short descriptive string attached to the RCommand, that allows the user to make some sense of what this command is all about. 113 @param receiver The RCommandReceiver this command should be passed on to, when finished. @Note: consider connecting to the notifier(), instead! 114 @param flags A freely assignable integer, that you can use to identify what the command was all about. Only the RCommandReceiver handling the results will have to know what exactly the flags mean. 115 */ 116 explicit RCommand (const QString &command, int type, const QString &rk_equiv = QString (), RCommandReceiver *receiver=0, int flags=0); 117 /** destructor. Note: you should not delete RCommands manually. This is done in RInterface. TODO: make protected */ 118 ~RCommand(); 119 /** @returns the type as specified in RCommand::RCommand */ type()120 int type () const { return _type; }; 121 /** @returns the raw command status. @see CommandStatus */ getStatus()122 int getStatus () const { return status; }; 123 /** @returns the rk_equiv as specified in RCommand::RCommand */ rkEquivalent()124 QString rkEquivalent () const { return _rk_equiv; }; 125 /** @returns the command string (i.e. the input) as specified in RCommand::RCommand */ command()126 QString command () const { return _command; }; 127 /** @returns like command(), but for user commands, which have been run, partially, returns only the remaining portion of the command. */ 128 QString remainingCommand () const; 129 /** Each RCommand is assigned a unique integer id (incrementing from 0 to integer overflow) upon creation. This returns this id. 130 @returns the unique id of this command */ id()131 int id () const { return _id; }; 132 /* TODO: Adjust these two functions to allow re-getting of output and error-messages from logs */ 133 /** @returns the full output of the command, i.e. all "regular" output, warning messages, and errors, in the order they were encountered. @see RCommand::output @see RCommand::error @see RCommand::warnings */ 134 QString fullOutput () const; 135 /** @returns the "regular" (ROutput::Output) output of the command, if any (e.g. "[1] 1" for "print (1)"). @see RCommand::succeeded @see RCommand::hasOutput */ 136 QString output () const; 137 /** @returns the warning message(s) given by R, if any. @see RCommand::output @see RCommand::error */ 138 QString warnings () const; 139 /** @returns the error message given by R, if any. @see RCommand::failed @see RCommand::hasError */ 140 QString error () const; 141 /** Types of commands (potentially more to come), bitwise or-able, 142 although partially exclusive. See \ref UsingTheInterfaceToR for a overview of what these are used for. TODO: find out, why Canceled is in here, and document that fact. */ 143 enum CommandTypes { 144 User=1, /**< Command was created directly by the user (e.g. in the console or in a command editor window) */ 145 Plugin=1 << 1, /**< Command comes from a plugin */ 146 App=1 << 2, /**< Command comes from the application (e.g. loading / saving the workspace */ 147 Sync=1 << 3, /**< Command is used to sync data to or from R-space. Typically used in the editor classes */ 148 EmptyCommand=1 << 4, /**< Command is empty and will not be processed (an empty command may be used as a "marker") */ 149 Console=1 << 5, /**< Command originated in the console. These commands will get some extra treatment in RKwatch */ 150 Internal=1 << 6, /**< Command is meant to be used in the backend, only. Do not use outside rbackend classes! */ 151 Silent=1 << 7, /**< Command can be interrupted, but is otherwise an internal command. In particular it should not be carbon copied to the output. */ 152 GetIntVector=1 << 8, /**< Try to fetch result as an array of integers */ 153 GetStringVector=1 << 9, /**< Try to fetch result as an array of chars */ 154 GetRealVector=1 << 10, /**< Try to fetch result as an array of doubles */ 155 GetStructuredData=1 << 11, /**< Try to fetch result as an RData structure */ 156 CCOutput=1 << 12, /**< Append command output to the HTML-output file */ 157 CCCommand=1 << 13, /**< Append the command itself to the HTML-output file */ 158 ObjectListUpdate=1 << 14, /**< The command may change the list of objects available. Do an update */ 159 QuitCommand=1 << 15, /**< The R backend should be killed */ 160 PriorityCommand=1 << 16 /**< The command has high priority, should be run during R's event loop processing. In general, PriorityCommands *must* not have side-effects 161 Use only, when absolutely necessary. */ 162 }; 163 enum CommandStatus { 164 Running=1, /**< command is currently running */ 165 WasTried=2, /**< the command has been passed to the backend. */ 166 Failed=4, /**< the command failed */ 167 HasOutput=8, /**< command has a string output retrievable via RCommand::output () */ 168 HasError=16, /**< command has an error-message retrievable via RCommand::error () */ 169 HasWarnings=32, /**< command has warning-message(s) retrievable via RCommand::warnings () */ 170 ErrorIncomplete=512, /**< backend rejected command as being incomplete */ 171 ErrorSyntax=1024, /**< backend rejected command as having a syntax error */ 172 ErrorOther=2048, /**< another error (not incomplete, not syntax error) has occurred while trying to execute the command */ 173 Canceled=8192 /**< Command was cancelled. */ 174 }; 175 /** the command has been passed to the backend. */ wasTried()176 bool wasTried () const { return (status & WasTried); }; 177 /** the command failed */ failed()178 bool failed () const { return (status & Failed); }; 179 /** the command was cancelled before it was executed */ wasCanceled()180 bool wasCanceled () const { return (wasTried () && failed () && (status & Canceled)); } 181 /** the command succeeded (wasTried () && (!failed ()) */ succeeded()182 bool succeeded () const { return ((status & WasTried) && !(status & Failed)); }; 183 /** command has a string output retrievable via RCommand::output () */ hasOutput()184 bool hasOutput () const { return (status & HasOutput); }; 185 /** command has a string output retrievable via RCommand::warnings () */ hasWarnings()186 bool hasWarnings () const { return (status & HasWarnings); }; 187 /** command has an error-message retrievable via RCommand::error () */ hasError()188 bool hasError () const { return (status & HasError); }; 189 /** backend rejected command as being incomplete */ errorIncomplete()190 bool errorIncomplete () const { return (status & ErrorIncomplete); }; 191 /** backend rejected command as having a syntax error */ errorSyntax()192 bool errorSyntax () const { return (status & ErrorSyntax); }; 193 /** return the flags associated with the command. Those are the same that you specified in the constructor, RKWard does not touch them. @see RCommand::RCommand */ getFlags()194 int getFlags () const { return (_flags); }; 195 /** Add an additional listener to the command */ 196 void addReceiver (RCommandReceiver *receiver); 197 /** Remove a receiver from the list. This may be needed when a listener wants to self-destruct, to make sure we don't try to send any further info there */ 198 void removeReceiver (RCommandReceiver *receiver); addTypeFlag(int flag)199 void addTypeFlag (int flag) { _type |= flag; }; getOutput()200 ROutputList &getOutput () { return output_list; }; 201 /** modify the command string. DO NOT CALL THIS after the command has been submitted! */ setCommand(const QString & command)202 void setCommand (const QString &command) { _command = command; }; 203 204 /** creates a proxy for this RCommand */ 205 RCommandProxy* makeProxy () const; 206 void mergeAndDeleteProxy (RCommandProxy *proxy); 207 208 /** returns a notifier for this command (creating it, if needed). You can connect to the notifiers signals. */ 209 RCommandNotifier* notifier (); 210 /** same as RObject::rQuote */ 211 static QString rQuote (const QString "ed); 212 private: 213 friend class RInterface; 214 friend class RCommandStack; 215 friend class RCommandStackModel; 216 /** internal function will be called by the backend, as the command gets passed through. Takes care of sending this command (back) to its receiver(s) */ 217 void finished (); 218 /** new output was generated. Pass on to receiver(s) */ 219 void newOutput (ROutput *output); 220 /** next line of command has been transmitted. Pass on to receiver(s). Only called for RCommand::User type commands */ 221 void commandLineIn (); 222 ROutputList output_list; 223 QString _command; 224 int _type; 225 int _flags; 226 int status; 227 int has_been_run_up_to; 228 QString _rk_equiv; 229 int _id; 230 static int next_id; 231 RCommandReceiver *receivers[MAX_RECEIVERS_PER_RCOMMAND]; 232 233 RCommandNotifier *_notifier; 234 }; 235 236 #endif 237