/* * adhoc.cpp - Client & Server implementation of JEP-50 (Ad-Hoc Commands) * Copyright (C) 2005 Remko Troncon * * 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 option) 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 library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include "adhoc.h" #include "psiaccount.h" #include "xmpp_xmlcommon.h" #include "xmpp_tasks.h" #include "xmpp_xdata.h" #include "xdata_widget.h" using namespace XMPP; #define AHC_NS "http://jabber.org/protocol/commands" #define XMPPSTANZA_NS "urn:ietf:params:xml:ns:xmpp-stanzas" // -------------------------------------------------------------------------- // AHCommand: The class representing an Ad-Hoc command request or reply. // -------------------------------------------------------------------------- AHCommand::AHCommand(const QString& node, const QString& sessionId, Action action) : node_(node), hasData_(false), status_(NoStatus), defaultAction_(NoAction), action_(action), sessionId_(sessionId) { } AHCommand::AHCommand(const QString& node, XData data, const QString& sessionId, Action action) : node_(node), hasData_(true), data_(data), status_(NoStatus), defaultAction_(NoAction), action_(action), sessionId_(sessionId) { } AHCommand::AHCommand(const QDomElement& q) : hasData_(false), defaultAction_(NoAction) { // Parse attributes QString status = q.attribute("status"); setStatus(string2status(status)); node_ = q.attribute("node"); action_ = string2action(q.attribute("action")); sessionId_ = q.attribute("sessionid"); // Parse the body for (QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement e = n.toElement(); if (e.isNull()) continue; QString tag = e.tagName(); // A form if (tag == "x" && e.attribute("xmlns") =="jabber:x:data") { data_.fromXml(e); hasData_ = true; } // Actions else if (tag == "actions") { QString execute = e.attribute("execute"); if (!execute.isEmpty()) setDefaultAction(string2action(execute)); for (QDomNode m = e.firstChild(); !m.isNull(); m = m.nextSibling()) { Action a = string2action(m.toElement().tagName()); if (a == Prev || a == Next || a == Complete) actions_ += a; } } } } QDomElement AHCommand::toXml(QDomDocument* doc, bool submit) const { QDomElement command = doc->createElement("command"); command.setAttribute("xmlns", AHC_NS); if (status_ != NoStatus) command.setAttribute("status",status2string(status())); if (hasData()) command.appendChild(data().toXml(doc, submit)); if (action_ != Execute) command.setAttribute("action",action2string(action_)); command.setAttribute("node", node_); if (!sessionId_.isEmpty()) command.setAttribute("sessionid", sessionId_); return command; } AHCommand AHCommand::formReply(const AHCommand& c, const XData& data) { AHCommand r(c.node(), data, c.sessionId()); r.setStatus(AHCommand::Executing); return r; } AHCommand AHCommand::formReply(const AHCommand& c, const XData& data, const QString& sessionId) { AHCommand r(c.node(), data, sessionId); r.setStatus(AHCommand::Executing); return r; } AHCommand AHCommand::canceledReply(const AHCommand& c) { AHCommand r(c.node(), c.sessionId()); r.setStatus(Canceled); return r; } AHCommand AHCommand::completedReply(const AHCommand& c) { AHCommand r(c.node(), c.sessionId()); r.setStatus(Completed); return r; } AHCommand AHCommand::completedReply(const AHCommand& c, const XData& d) { AHCommand r(c.node(), d, c.sessionId()); r.setStatus(Completed); return r; } //AHCommand AHCommand::errorReply(const AHCommand& c, const AHCError& error) //{ // AHCommand r(c.node(), c.sessionId()); // r.setError(error); // return r; //} void AHCommand::setStatus(Status s) { status_ = s; } void AHCommand::setError(const AHCError& e) { error_ = e; } void AHCommand::setDefaultAction(Action a) { defaultAction_ = a; } QString AHCommand::status2string(Status status) { QString s; switch (status) { case Executing : s = "executing"; break; case Completed : s = "completed"; break; case Canceled : s = "canceled"; break; case NoStatus : s = ""; break; } return s; } QString AHCommand::action2string(Action action) { QString s; switch (action) { case Prev : s = "prev"; break; case Next : s = "next"; break; case Cancel : s = "cancel"; break; case Complete : s = "complete"; break; default: break; } return s; } AHCommand::Action AHCommand::string2action(const QString& s) { if (s == "prev") return Prev; else if (s == "next") return Next; else if (s == "complete") return Complete; else if (s == "cancel") return Cancel; else return Execute; } AHCommand::Status AHCommand::string2status(const QString& s) { if (s == "canceled") return Canceled; else if (s == "completed") return Completed; else if (s == "executing") return Executing; else return NoStatus; } // -------------------------------------------------------------------------- // AHCError: The class representing an Ad-Hoc command error // -------------------------------------------------------------------------- AHCError::AHCError(ErrorType t) : type_(t) { } AHCError::AHCError(const QDomElement& e) : type_(None) { QString errorGeneral = "", errorSpecific = ""; for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); if(i.isNull()) continue; QString tag = i.tagName(); if ((tag == "bad-request" || tag == "not-allowed" || tag == "forbidden" || tag == "forbidden" || tag == "item-not-found" || tag == "feature-not-implemented") && e.attribute("xmlns") == XMPPSTANZA_NS) { errorGeneral = tag; } else if ((tag == "malformed-action" || tag == "bad-action" || tag == "bad-locale" || tag == "bad-payload" || tag == "bad-sessionid" || tag == "session-expired") && e.attribute("xmlns") == AHC_NS) { errorSpecific = tag; } } type_ = strings2error(errorGeneral, errorSpecific); } QDomElement AHCError::toXml(QDomDocument* doc) const { QDomElement err = doc->createElement("error"); // Error handling if (type_ != None) { QString desc, specificCondition = ""; switch (type_) { case MalformedAction: desc = "bad-request"; specificCondition = "malformed-action"; break; case BadAction: desc = "bad-request"; specificCondition = "bad-action"; break; case BadLocale: desc = "bad-request"; specificCondition = "bad-locale"; break; case BadPayload: desc = "bad-request"; specificCondition = "bad-payload"; break; case BadSessionID: desc = "bad-request"; specificCondition = "bad-sessionid"; break; case SessionExpired: desc = "not-allowed"; specificCondition = "session-expired"; break; case Forbidden: desc = "forbidden"; break; case ItemNotFound: desc = "item-not-found"; break; case FeatureNotImplemented: desc = "feature-not-implemented"; break; case None: break; } // General error condition QDomElement generalElement = doc->createElement(desc); generalElement.setAttribute("xmlns", XMPPSTANZA_NS); err.appendChild(generalElement); // Specific error condition if (!specificCondition.isEmpty()) { QDomElement generalElement = doc->createElement(specificCondition); generalElement.setAttribute("xmlns", AHC_NS); err.appendChild(generalElement); } } return err; } AHCError::ErrorType AHCError::strings2error(const QString& g, const QString& s) { if (s == "malformed-action") return MalformedAction; if (s == "bad-action") return BadAction; if (s == "bad-locale") return BadLocale; if (s == "bad-payload") return BadPayload; if (s == "bad-sessionid") return BadSessionID; if (s == "session-expired") return SessionExpired; if (g == "forbidden") return Forbidden; if (g == "item-not-found") return ItemNotFound; if (g == "feature-not-implemented") return FeatureNotImplemented; return None; } QString AHCError::error2description(const AHCError& e) { QString desc; switch (e.type()) { case MalformedAction: desc = QString("The responding JID does not understand the specified action"); break; case BadAction: desc = QString("The responding JID cannot accept the specified action"); break; case BadLocale: desc = QString("The responding JID cannot accept the specified language/locale"); break; case BadPayload: desc = QString("The responding JID cannot accept the specified payload (eg the data form did not provide one or more required fields)"); break; case BadSessionID: desc = QString("The responding JID cannot accept the specified sessionid"); break; case SessionExpired: desc = QString("The requesting JID specified a sessionid that is no longer active (either because it was completed, canceled, or timed out)"); break; case Forbidden: desc = QString("The requesting JID is not allowed to execute the command"); break; case ItemNotFound: desc = QString("The responding JID cannot find the requested command node"); break; case FeatureNotImplemented: desc = QString("The responding JID does not support Ad-hoc commands"); break; case None: break; } return desc; } // -------------------------------------------------------------------------- // AHCommandServer: The server-side implementation of an Ad-hoc command. // -------------------------------------------------------------------------- AHCommandServer::AHCommandServer(AHCServerManager* manager) : manager_(manager) { manager_->addServer(this); } // -------------------------------------------------------------------------- // JT_AHCServer: Task to handle ad-hoc command requests // -------------------------------------------------------------------------- class JT_AHCServer : public Task { Q_OBJECT public: JT_AHCServer(Task*, AHCServerManager*); bool take(const QDomElement& e); void sendReply(const AHCommand&, const Jid& to, const QString& id); protected: bool commandListQuery(const QDomElement& e); bool commandExecuteQuery(const QDomElement& e); void sendCommandList(const QString& to, const QString& from, const QString& id); private: AHCServerManager* manager_; }; JT_AHCServer::JT_AHCServer(Task* t, AHCServerManager* manager) : Task(t), manager_(manager) { } bool JT_AHCServer::take(const QDomElement& e) { // Check if it's a query if (e.tagName() != "iq") return false; return (commandListQuery(e) || commandExecuteQuery(e)); } bool JT_AHCServer::commandListQuery(const QDomElement& e) { if (e.attribute("type") == "get") { bool found; QDomElement q = findSubTag(e, "query", &found); if (found && q.attribute("xmlns") == "http://jabber.org/protocol/disco#items" && q.attribute("node") == AHC_NS) { sendCommandList(e.attribute("from"),e.attribute("to"),e.attribute("id")); return true; } else if (found && q.attribute("xmlns") == "http://jabber.org/protocol/disco#info" && q.attribute("node") == AHC_NS) { QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); QDomElement query = doc()->createElement("query"); query.setAttribute("xmlns", "http://jabber.org/protocol/disco#info"); iq.appendChild(query); send(iq); return true; } else if (found && q.attribute("xmlns") == "http://jabber.org/protocol/disco#items" && manager_->hasServer(q.attribute("node"), Jid(e.attribute("from")))) { QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); QDomElement query = doc()->createElement("query"); query.setAttribute("xmlns", "http://jabber.org/protocol/disco#items"); query.setAttribute("node",q.attribute("node")); iq.appendChild(query); send(iq); return true; } else if (found && q.attribute("xmlns") == "http://jabber.org/protocol/disco#info" && manager_->hasServer(q.attribute("node"), Jid(e.attribute("from")))) { QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); QDomElement query = doc()->createElement("query"); query.setAttribute("xmlns", "http://jabber.org/protocol/disco#info"); query.setAttribute("node",q.attribute("node")); iq.appendChild(query); QDomElement identity; QDomElement feature; identity = doc()->createElement("identity"); identity.setAttribute("category", "automation"); identity.setAttribute("type", "command-node"); query.appendChild(identity); feature = doc()->createElement("feature"); feature.setAttribute("var", AHC_NS); query.appendChild(feature); feature = doc()->createElement("feature"); feature.setAttribute("var", "jabber:x:data"); query.appendChild(feature); send(iq); return true; } } return false; } bool JT_AHCServer::commandExecuteQuery(const QDomElement& e) { if (e.attribute("type") == "set") { bool found; QDomElement q = findSubTag(e, "command", &found); if (found && q.attribute("xmlns") == AHC_NS) { if (manager_->hasServer(q.attribute("node"), Jid(e.attribute("from")))) { AHCommand command(q); manager_->execute(command, Jid(e.attribute("from")), e.attribute("id")); return true; } return false; } else return false; } return false; } void JT_AHCServer::sendCommandList(const QString& to, const QString& from, const QString& id) { // Create query element QDomElement iq = createIQ(doc(), "result", to, id); QDomElement query = doc()->createElement("query"); query.setAttribute("xmlns", "http://jabber.org/protocol/disco#items"); query.setAttribute("node", AHC_NS); iq.appendChild(query); // Add all commands AHCServerManager::ServerList l = manager_->commands(Jid(to)); for (AHCommandServer* c = l.first(); c; c = l.next()) { QDomElement command = doc()->createElement("item"); command.setAttribute("jid",from); command.setAttribute("name",c->name()); command.setAttribute("node",c->node()); query.appendChild(command); } // Send the message send(iq); } void JT_AHCServer::sendReply(const AHCommand& c, const Jid& to, const QString& id) { // if (c.error().type() != AHCError::None) { QDomElement iq = createIQ(doc(), "result", to.full(), id); QDomElement command = c.toXml(doc(), false); iq.appendChild(command); send(iq); // } // else { // } } // -------------------------------------------------------------------------- AHCServerManager::AHCServerManager(PsiAccount *pa) : pa_(pa) { server_task_ = new JT_AHCServer(pa_->client()->rootTask(), this); } void AHCServerManager::addServer(AHCommandServer* server) { servers_.append(server); } AHCServerManager::ServerList AHCServerManager::commands(const Jid& j) const { ServerList list; for (ServerList::ConstIterator it = servers_.begin(); it != servers_.end(); ++it) { if ((*it)->isAllowed(j)) list.append(*it); } return list; } void AHCServerManager::execute(const AHCommand& command, const Jid& requester, QString id) { AHCommandServer* c = findServer(command.node()); // Check if the command is provided if (!c) { //server_task_->sendReply(AHCommand::errorReply(command,AHCError(AHCError::ItemNotFound)), requester, id); return; } // Check if the requester is allowed to execute the command if (c->isAllowed(requester)) { if (command.action() == AHCommand::Cancel) { c->cancel(command); server_task_->sendReply(AHCommand::canceledReply(command), requester, id); } else // Execute the command & send back the response server_task_->sendReply(c->execute(command, requester), requester, id); } else { //server_task_->sendReply(AHCommand::errorReply(command,AHCError(AHCError::Forbidden)), requester, id); return; } } AHCommandServer* AHCServerManager::findServer(const QString& node) const { for (ServerList::ConstIterator it = servers_.begin(); it != servers_.end(); ++it) { if ((*it)->node() == node) return (*it); } return 0; } bool AHCServerManager::hasServer(const QString& node, const Jid& requester) const { AHCommandServer* c = findServer(node); // Check if the command is provided if (!c) { return false; } if (c->isAllowed(requester)) { return true; } else { return false; } } // -------------------------------------------------------------------------- bool operator<(const AHCommandItem &ci1, const AHCommandItem &ci2) { return ci1.name < ci2.name; } bool operator<=(const AHCommandItem &ci1, const AHCommandItem &ci2) { return ci1.name <= ci2.name; } bool operator==(const AHCommandItem &ci1, const AHCommandItem &ci2) { return ci1.name == ci2.name; } bool operator>(const AHCommandItem &ci1, const AHCommandItem &ci2) { return ci1.name > ci2.name; } bool operator>=(const AHCommandItem &ci1, const AHCommandItem &ci2) { return ci1.name >= ci2.name; } // -------------------------------------------------------------------------- // JT_AHCGetList: A Task to retreive the available commands of a client // -------------------------------------------------------------------------- class JT_AHCGetList : public Task { public: JT_AHCGetList(Task* t, const Jid& j); void onGo(); bool take(const QDomElement &x); const QValueList& commands() const { return commands_; } private: Jid receiver_; QValueList commands_; }; JT_AHCGetList::JT_AHCGetList(Task* t, const Jid& j) : Task(t), receiver_(j) { } void JT_AHCGetList::onGo() { QDomElement e = createIQ(doc(), "get", receiver_.full(), id()); QDomElement q = doc()->createElement("query"); q.setAttribute("xmlns", "http://jabber.org/protocol/disco#items"); q.setAttribute("node", AHC_NS); e.appendChild(q); send(e); } bool JT_AHCGetList::take(const QDomElement& e) { if(!iqVerify(e, receiver_, id())) { return false; } if (e.attribute("type") == "result") { // Extract commands commands_.clear(); bool found; QDomElement commands = findSubTag(e, "query", &found); if(found) { for(QDomNode n = commands.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); if(i.isNull()) continue; if(i.tagName() == "item") { AHCommandItem ci; ci.node = i.attribute("node"); ci.name = i.attribute("name"); ci.jid = i.attribute("jid"); commands_ += ci; } } qHeapSort(commands_); } setSuccess(); return true; } else { setError(e); return false; } } // -------------------------------------------------------------------------- // -------------------------------------------------------------------------- // JT_AHCExecute: A task to execute a command // -------------------------------------------------------------------------- class JT_AHCExecute : public Task { public: JT_AHCExecute(Task* t, PsiAccount* pa, Jid j, const AHCommand&); void onGo(); bool take(const QDomElement &x); private: Jid receiver_; PsiAccount* account_; AHCommand command_; }; JT_AHCExecute::JT_AHCExecute(Task* t, PsiAccount* pa, Jid j, const AHCommand& command) : Task(t), receiver_(j), account_(pa), command_(command) { } void JT_AHCExecute::onGo() { QDomElement e = createIQ(doc(), "set", receiver_.full(), id()); e.appendChild(command_.toXml(doc(),true)); send(e); } bool JT_AHCExecute::take(const QDomElement& e) { if(!iqVerify(e, receiver_, id())) { return false; } // Result of a command if (e.attribute("type") == "result") { bool found; QDomElement i = findSubTag(e, "command", &found); if (found) { AHCommand c(i); if (c.status() == AHCommand::Executing) { AHCFormDlg *w = new AHCFormDlg(c,receiver_,account_); w->show(); } else if (c.status() == AHCommand::Completed && i.childNodes().count() > 0) { AHCFormDlg *w = new AHCFormDlg(c,receiver_,account_, true); w->show(); } setSuccess(); return true; } } // Error /*else if (e.attribute("type") == "set") { AHCError err(e); if (err.type() != None) { QMessageBox::critical(0, tr("Error"), AHCommand::error2description(err.type()), QMessageBox::Ok, QMessageBox::NoButton); } return true; }*/ setError(e); return false; } // -------------------------------------------------------------------------- // -------------------------------------------------------------------------- // AHCommandDlg // -------------------------------------------------------------------------- AHCommandDlg::AHCommandDlg(PsiAccount* pa, const Jid& receiver) : pa_(pa), receiver_(receiver) { QVBoxLayout *vb = new QVBoxLayout(this, 11, 6); // Command list + Buttons QLabel* lb_commands = new QLabel(tr("Command:"),this); vb->addWidget(lb_commands); QHBoxLayout *hb1 = new QHBoxLayout(vb); cb_commands = new QComboBox(this); cb_commands->setSizePolicy ( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); hb1->addWidget(cb_commands); /*pb_info = new QPushButton(tr("Info"), this); hb1->addWidget(pb_info);*/ pb_execute = new QPushButton(tr("Execute"), this); hb1->addWidget(pb_execute); connect(pb_execute, SIGNAL(clicked()), SLOT(executeCommand())); vb->addStretch(1); // Bottom row QHBoxLayout *hb2 = new QHBoxLayout(vb); busy = new BusyWidget(this); hb2->addWidget(busy); hb2->addStretch(1); // Refresh button pb_refresh = new QPushButton(tr("Refresh"), this); hb2->addWidget(pb_refresh); connect(pb_refresh, SIGNAL(clicked()), SLOT(refreshCommands())); // Close button pb_close = new QPushButton(tr("Close"), this); hb2->addWidget(pb_close); connect(pb_close, SIGNAL(clicked()), SLOT(close())); pb_close->setDefault(true); pb_close->setFocus(); setCaption(QString("Execute Command (%1)").arg(receiver.full())); // Initialize other things task_list_ = 0; // Load commands refreshCommands(); } void AHCommandDlg::refreshCommands() { cb_commands->clear(); pb_execute->setEnabled(false); //pb_info->setEnabled(false); busy->start(); if (task_list_) disconnect(task_list_,SIGNAL(finished()),this,SLOT(listReceived())); task_list_= new JT_AHCGetList(pa_->client()->rootTask(),receiver_); connect(task_list_,SIGNAL(finished()),SLOT(listReceived())); task_list_->go(true); } void AHCommandDlg::listReceived() { QValueList l = task_list_->commands(); QValueList::ConstIterator it; for (it = l.begin(); it != l.end(); ++it) { cb_commands->insertItem((*it).name); commands_.append(*it); } pb_execute->setEnabled(cb_commands->count()>0); busy->stop(); // FIXME delete task_list_ ?; task_list_ = 0; } void AHCommandDlg::executeCommand() { if (cb_commands->count() > 0) { busy->start(); Jid to(commands_[cb_commands->currentItem()].jid); QString node = commands_[cb_commands->currentItem()].node; JT_AHCExecute* t = new JT_AHCExecute(pa_->client()->rootTask(),pa_,to,AHCommand(node)); connect(t,SIGNAL(finished()),SLOT(commandExecuted())); t->go(true); } } void AHCommandDlg::commandExecuted() { busy->stop(); close(); } void AHCommandDlg::executeCommand(PsiAccount* pa, const Jid& j, const QString &node) { JT_AHCExecute* t = new JT_AHCExecute(pa->client()->rootTask(),pa,j,AHCommand(node)); t->go(true); } // -------------------------------------------------------------------------- AHCFormDlg::AHCFormDlg(const AHCommand& r, const Jid& receiver, PsiAccount* account, bool final) : receiver_(receiver), account_(account) { // Save node node_ = r.node(); sessionId_ = r.sessionId(); QVBoxLayout *vb = new QVBoxLayout(this, 11, 6); // Instructions if (!r.data().instructions().isEmpty()) { QLabel* lb_instructions = new QLabel(r.data().instructions(),this); vb->addWidget(lb_instructions); } // XData form xdata_ = new XDataWidget(this); xdata_->setFields(r.data().fields()); vb->addWidget(xdata_); vb->addStretch(1); // Buttons QHBoxLayout *hb = new QHBoxLayout(vb); pb_complete = pb_cancel = pb_prev = pb_next = 0; if (!final) { busy = new BusyWidget(this); hb->addWidget(busy); hb->addStretch(1); if (r.actions().empty()) { // Single stage dialog pb_complete = new QPushButton(tr("Finish"),this); connect(pb_complete,SIGNAL(clicked()),SLOT(doExecute())); hb->addWidget(pb_complete); } else { // Multi-stage dialog // Previous pb_prev = new QPushButton(tr("Previous"),this); if (r.actions().contains(AHCommand::Prev)) { if (r.defaultAction() == AHCommand::Prev) { connect(pb_prev,SIGNAL(clicked()),SLOT(doExecute())); pb_prev->setDefault(true); pb_prev->setFocus(); } else connect(pb_prev,SIGNAL(clicked()),SLOT(doPrev())); pb_prev->setEnabled(true); } else pb_prev->setEnabled(false); hb->addWidget(pb_prev); // Next pb_next = new QPushButton(tr("Next"),this); if (r.actions().contains(AHCommand::Next)) { if (r.defaultAction() == AHCommand::Next) { connect(pb_next,SIGNAL(clicked()),SLOT(doExecute())); pb_next->setDefault(true); pb_next->setFocus(); } else connect(pb_next,SIGNAL(clicked()),SLOT(doNext())); pb_next->setEnabled(true); } else { pb_next->setEnabled(false); } hb->addWidget(pb_next); // Complete pb_complete = new QPushButton(tr("Finish"),this); if (r.actions().contains(AHCommand::Complete)) { if (r.defaultAction() == AHCommand::Complete) { connect(pb_complete,SIGNAL(clicked()),SLOT(doExecute())); pb_complete->setDefault(true); pb_complete->setFocus(); } else connect(pb_complete,SIGNAL(clicked()),SLOT(doComplete())); pb_complete->setEnabled(true); } else { pb_complete->setEnabled(false); } hb->addWidget(pb_complete); } pb_cancel = new QPushButton(tr("Cancel"), this); connect(pb_cancel, SIGNAL(clicked()),SLOT(doCancel())); hb->addWidget(pb_cancel); } else { pb_complete = new QPushButton(tr("Ok"),this); connect(pb_complete,SIGNAL(clicked()),SLOT(close())); hb->addWidget(pb_complete); } if (!r.data().title().isEmpty()) { setCaption(QString("%1 (%2)").arg(r.data().title()).arg(receiver.full())); } else { setCaption(QString("%1").arg(receiver.full())); } } void AHCFormDlg::doPrev() { busy->start(); JT_AHCExecute* t = new JT_AHCExecute(account_->client()->rootTask(),account_,receiver_,AHCommand(node_,data(),sessionId_,AHCommand::Prev)); connect(t,SIGNAL(finished()),SLOT(commandExecuted())); t->go(true); } void AHCFormDlg::doNext() { busy->start(); JT_AHCExecute* t = new JT_AHCExecute(account_->client()->rootTask(),account_,receiver_,AHCommand(node_,data(),sessionId_,AHCommand::Next)); connect(t,SIGNAL(finished()),SLOT(commandExecuted())); t->go(true); } void AHCFormDlg::doExecute() { busy->start(); JT_AHCExecute* t = new JT_AHCExecute(account_->client()->rootTask(),account_,receiver_,AHCommand(node_,data(),sessionId_)); connect(t,SIGNAL(finished()),SLOT(commandExecuted())); t->go(true); } void AHCFormDlg::doComplete() { busy->start(); JT_AHCExecute* t = new JT_AHCExecute(account_->client()->rootTask(),account_,receiver_,AHCommand(node_,data(),sessionId_,AHCommand::Complete)); connect(t,SIGNAL(finished()),SLOT(commandExecuted())); t->go(true); } void AHCFormDlg::doCancel() { busy->start(); JT_AHCExecute* t = new JT_AHCExecute(account_->client()->rootTask(),account_,receiver_,AHCommand(node_,sessionId_,AHCommand::Cancel)); connect(t,SIGNAL(finished()),SLOT(commandExecuted())); t->go(true); } void AHCFormDlg::commandExecuted() { busy->stop(); close(); } XData AHCFormDlg::data() const { XData x; x.setFields(xdata_->fields()); x.setType(XData::Data_Submit); return x; } // -------------------------------------------------------------------------- #include "adhoc.moc"