1 /***************************************************************************
2                           rcommand.cpp  -  description
3                              -------------------
4     begin                : Mon Nov 11 2002
5     copyright            : (C) 2002, 2006, 2007 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 #include "rcommand.h"
19 #include "rcommandreceiver.h"
20 #include "rkrinterface.h"
21 #include "../windows/rkcommandlog.h"
22 #include "rkrbackendprotocol_shared.h"
23 #include "../core/robject.h"
24 
25 #include "../debug.h"
26 #include "../rkglobals.h"
27 
toCommand()28 RCommand* RCommandChain::toCommand() {
29 	return (is_command ? static_cast<RCommand*> (this) : 0);
30 }
31 
32 
RCommandNotifier()33 RCommandNotifier::RCommandNotifier () : QObject () {
34 	RK_TRACE (RBACKEND);
35 }
36 
~RCommandNotifier()37 RCommandNotifier::~RCommandNotifier () {
38 	RK_TRACE (RBACKEND);
39 }
40 
41 int RCommand::next_id = 0;
42 
RCommand(const QString & command,int type,const QString & rk_equiv,RCommandReceiver * receiver,int flags)43 RCommand::RCommand(const QString &command, int type, const QString &rk_equiv, RCommandReceiver *receiver, int flags) : RData (), RCommandChain (false) {
44 	RK_TRACE (RBACKEND);
45 	_id = next_id++;
46 // if we ever submit enough commands to get a buffer overflow, use only positive numbers.
47 	if (next_id < 0) {
48 		next_id = 0;
49 	}
50 	_type = type;
51 	_flags = flags;
52 	if (type & Plugin) _command = command.trimmed ();
53 	else _command = command;
54 	if (_command.isEmpty ()) _type |= EmptyCommand;
55 	status = 0;
56 	has_been_run_up_to = 0;
57 	_rk_equiv = rk_equiv;
58 	_notifier = 0;
59 	for (int i = 0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) receivers[i] = 0;
60 	if (!(type & Internal)) {
61 		addReceiver (receiver);
62 		addReceiver (RKCommandLog::getLog ());
63 	}
64 }
65 
~RCommand()66 RCommand::~RCommand(){
67 	RK_TRACE (RBACKEND);
68 
69 	for (QList<ROutput*>::const_iterator it = output_list.constBegin (); it != output_list.constEnd (); ++it) {
70 		delete (*it);
71 	}
72 	// The output_list itself is cleared automatically
73 
74 	if (_notifier) delete _notifier;
75 }
76 
notifier()77 RCommandNotifier* RCommand::notifier () {
78 	if (!_notifier) {
79 		RK_TRACE (RBACKEND);
80 		_notifier = new RCommandNotifier ();
81 		RK_ASSERT (_notifier);
82 	}
83 	return _notifier;
84 }
85 
addReceiver(RCommandReceiver * receiver)86 void RCommand::addReceiver (RCommandReceiver *receiver) {
87 	RK_TRACE (RBACKEND);
88 
89 	if (!receiver) return;
90 
91 	for (int i = 0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
92 		if (receivers[i] == 0) {
93 			receivers[i] = receiver;
94 			receiver->addCommand (this);
95 			return;
96 		}
97 	}
98 
99 	RK_DEBUG (RBACKEND, DL_ERROR, "Too many receivers for command");
100 }
101 
removeReceiver(RCommandReceiver * receiver)102 void RCommand::removeReceiver (RCommandReceiver *receiver) {
103 	RK_TRACE (RBACKEND);
104 
105 	if (!receiver) return;
106 
107 	for (int i = 0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
108 		if (receivers[i] == receiver) {
109 			receivers[i] = 0;
110 			return;
111 		}
112 	}
113 
114 	RK_DEBUG (RBACKEND, DL_WARNING, "Was not a receiver in RCommand::removeReceiver: %p", receiver);
115 }
116 
finished()117 void RCommand::finished () {
118 	RK_TRACE (RBACKEND);
119 
120 	for (int i=0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
121 		if (receivers[i] == 0) continue;
122 		receivers[i]->delCommand (this);
123 		receivers[i]->rCommandDone (this);
124 	}
125 	if (_notifier) _notifier->emitFinished (this);
126 }
127 
newOutput(ROutput * output)128 void RCommand::newOutput (ROutput *output) {
129 	RK_TRACE (RBACKEND);
130 
131 	for (int i=0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
132 		if (receivers[i] == 0) continue;
133 		receivers[i]->newOutput (this, output);
134 	}
135 }
136 
commandLineIn()137 void RCommand::commandLineIn () {
138 	RK_TRACE (RBACKEND);
139 	RK_ASSERT (_type & User);
140 
141 	for (int i=0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
142 		if (receivers[i] == 0) continue;
143 		receivers[i]->userCommandLineIn (this);
144 	}
145 }
146 
error() const147 QString RCommand::error () const {
148 	RK_TRACE (RBACKEND);
149 
150 	QString ret;
151 	for (ROutputList::const_iterator it = output_list.begin (); it != output_list.end (); ++it) {
152 		if ((*it)->type == ROutput::Error) {
153 			ret.append ((*it)->output);
154 		}
155 	}
156 	return ret;
157 }
158 
output() const159 QString RCommand::output () const {
160 	RK_TRACE (RBACKEND);
161 
162 	QString ret;
163 	for (ROutputList::const_iterator it = output_list.begin (); it != output_list.end (); ++it) {
164 		if ((*it)->type == ROutput::Output) {
165 			ret.append ((*it)->output);
166 		}
167 	}
168 	return ret;
169 }
170 
warnings() const171 QString RCommand::warnings () const {
172 	RK_TRACE (RBACKEND);
173 
174 	QString ret;
175 	for (ROutputList::const_iterator it = output_list.begin (); it != output_list.end (); ++it) {
176 		if ((*it)->type == ROutput::Warning) {
177 			ret.append ((*it)->output);
178 		}
179 	}
180 	return ret;
181 }
182 
fullOutput() const183 QString RCommand::fullOutput () const {
184 	RK_TRACE (RBACKEND);
185 
186 	QString ret;
187 	for (ROutputList::const_iterator it = output_list.begin (); it != output_list.end (); ++it) {
188 		ret.append ((*it)->output);
189 	}
190 	return ret;
191 }
192 
remainingCommand() const193 QString RCommand::remainingCommand () const {
194 	RK_TRACE (RBACKEND);
195 	RK_ASSERT (_type & User);	// not a grave problem, if it's not, but not useful, either
196 
197 	return _command.mid (has_been_run_up_to);
198 }
199 
mergeAndDeleteProxy(RCommandProxy * proxy)200 void RCommand::mergeAndDeleteProxy (RCommandProxy *proxy) {
201 	RK_TRACE (RBACKEND);
202 
203 	RK_ASSERT (proxy);
204 	RK_ASSERT (proxy->id == _id);
205 	RK_ASSERT (proxy->type == _type);
206 
207 	status = proxy->status;
208 	has_been_run_up_to = proxy->has_been_run_up_to;
209 	swallowData (*proxy);
210 	delete proxy;
211 }
212 
makeProxy() const213 RCommandProxy* RCommand::makeProxy () const {
214 	RK_TRACE (RBACKEND);
215 	RK_ASSERT (status == 0);	// Initialization from an already touched command is not a real problem, but certainly no expected usage
216 	RK_ASSERT (has_been_run_up_to == 0);
217 	RK_ASSERT (getDataType () == RData::NoData);
218 
219 	RCommandProxy *ret = new RCommandProxy (_command, _type);
220 	ret->id = _id,
221 	ret->status = status;
222 	ret->has_been_run_up_to = has_been_run_up_to;
223 	return ret;
224 }
225 
rQuote(const QString & quoted)226 QString RCommand::rQuote (const QString &quoted) {
227 	return RObject::rQuote (quoted);
228 }
229 
230