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 &quoted);
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