00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "DashelTarget.h"
00025 #include "../msg/msg.h"
00026 #include <algorithm>
00027 #include <iostream>
00028 #include <ostream>
00029 #include <sstream>
00030 #include <cassert>
00031 #include <QInputDialog>
00032 #include <QtGui>
00033 #include <QLibraryInfo>
00034 #include <stdexcept>
00035
00036
00037 #include <DashelTarget.moc>
00038
00039 #ifdef WIN32 // for Sleep
00040 #include <windows.h>
00041 #endif
00042
00043
00044 template<typename Derived, typename Base>
00045 static inline Derived polymorphic_downcast(Base base)
00046 {
00047 Derived derived = dynamic_cast<Derived>(base);
00048 if (!derived)
00049 abort();
00050 return derived;
00051 }
00052
00053 namespace Aseba
00054 {
00055 using std::copy;
00056 using namespace Dashel;
00057
00060
00061 DashelConnectionDialog::DashelConnectionDialog()
00062 {
00063 QSettings settings("EPFL-LSRO-Mobots", "Aseba Studio");
00064
00065 QVBoxLayout* mainLayout = new QVBoxLayout(this);
00066
00067 netGroupBox = new QGroupBox(tr("Network (TCP)"));
00068 netGroupBox->setCheckable(true);
00069 QGridLayout* netLayout = new QGridLayout;
00070 netLayout->addWidget(new QLabel(tr("Host")), 0, 0);
00071 netLayout->addWidget(new QLabel(tr("Port")), 0, 1);
00072 host = new QLineEdit(settings.value("tcp host", ASEBA_DEFAULT_HOST).toString());
00073 netLayout->addWidget(host, 1, 0);
00074 port = new QSpinBox();
00075 port->setMinimum(0);
00076 port->setMaximum(65535);
00077 port->setValue(settings.value("tcp port", ASEBA_DEFAULT_PORT).toInt());
00078 netLayout->addWidget(port, 1, 1);
00079 netGroupBox->setLayout(netLayout);
00080 connect(netGroupBox, SIGNAL(clicked()), SLOT(netGroupChecked()));
00081 mainLayout->addWidget(netGroupBox);
00082
00083 serialGroupBox = new QGroupBox(tr("Serial"));
00084 serialGroupBox->setCheckable(true);
00085 serialGroupBox->setChecked(false);
00086 QHBoxLayout* serialLayout = new QHBoxLayout();
00087 serial = new QListWidget();
00088 typedef std::map<int, std::pair<std::string, std::string> > PortsMap;
00089 PortsMap ports = SerialPortEnumerator::getPorts();
00090 for (PortsMap::const_iterator it = ports.begin(); it != ports.end(); ++it)
00091 {
00092 QListWidgetItem* item = new QListWidgetItem(QString(it->second.second.c_str()));
00093 item->setData(Qt::UserRole, QVariant(QString::fromUtf8(it->second.first.c_str())));
00094 serial->addItem(item);
00095
00096 }
00097 serial->setSelectionMode(QAbstractItemView::SingleSelection);
00098 serialLayout->addWidget(serial);
00099 connect(serial, SIGNAL(itemSelectionChanged()), SLOT(setupOkStateFromListSelection()));
00100 serialGroupBox->setLayout(serialLayout);
00101 connect(serialGroupBox, SIGNAL(clicked()), SLOT(serialGroupChecked()));
00102 mainLayout->addWidget(serialGroupBox);
00103
00104 customGroupBox = new QGroupBox(tr("Custom"));
00105 customGroupBox->setCheckable(true);
00106 customGroupBox->setChecked(false);
00107 QHBoxLayout* customLayout = new QHBoxLayout();
00108 custom = new QLineEdit(settings.value("custom target", ASEBA_DEFAULT_TARGET).toString());
00109 customLayout->addWidget(custom);
00110 customGroupBox->setLayout(customLayout);
00111 connect(customGroupBox, SIGNAL(clicked()), SLOT(customGroupChecked()));
00112 mainLayout->addWidget(customGroupBox);
00113
00114 languageSelectionBox = new QComboBox;
00115 languageSelectionBox->addItem(QString::fromUtf8("English"), "en");
00116 languageSelectionBox->addItem(QString::fromUtf8("Français"), "fr");
00117
00118 for (int i = 0; i < languageSelectionBox->count(); ++i)
00119 {
00120 if (QLocale::system().name().startsWith(languageSelectionBox->itemData(i).toString()))
00121 {
00122 languageSelectionBox->setCurrentIndex(i);
00123 break;
00124 }
00125 }
00126 mainLayout->addWidget(languageSelectionBox);
00127
00128 QHBoxLayout* buttonLayout = new QHBoxLayout();
00129 connectButton = new QPushButton(QIcon(":/images/ok.png"), tr("Connect"));
00130 connect(connectButton, SIGNAL(clicked(bool)), SLOT(accept()));
00131 buttonLayout->addWidget(connectButton);
00132 QPushButton* cancelButton = new QPushButton(QIcon(":/images/no.png"), tr("Cancel"));
00133 connect(cancelButton, SIGNAL(clicked(bool)), SLOT(reject()));
00134 buttonLayout->addWidget(cancelButton);
00135 mainLayout->addLayout(buttonLayout);
00136
00137 setWindowTitle(tr("Aseba Target Selection"));
00138 }
00139
00140 std::string DashelConnectionDialog::getTarget()
00141 {
00142 QSettings settings("EPFL-LSRO-Mobots", "Aseba Studio");
00143 if (netGroupBox->isChecked())
00144 {
00145 settings.setValue("tcp host", host->text());
00146 settings.setValue("tcp port", port->value());
00147 std::ostringstream oss;
00148 oss << "tcp:host=" << host->text().toStdString() << ";port=" << port->value();
00149 return oss.str();
00150 }
00151 else if (serialGroupBox->isChecked())
00152 {
00153 QString target("ser:device=%0");
00154 return target.arg(serial->selectionModel()->selectedRows().first().data(Qt::UserRole).toString()).toStdString();
00155 }
00156 else if (customGroupBox->isChecked())
00157 {
00158 settings.setValue("custom target", custom->text());
00159 return custom->text().toStdString();
00160 }
00161 else
00162 {
00163 assert(false);
00164 return "";
00165 }
00166 }
00167
00168 QString DashelConnectionDialog::getLocaleName()
00169 {
00170 return languageSelectionBox->itemData(languageSelectionBox->currentIndex()).toString();
00171 }
00172
00173 void DashelConnectionDialog::netGroupChecked()
00174 {
00175 netGroupBox->setChecked(true);
00176 serialGroupBox->setChecked(false);
00177 customGroupBox->setChecked(false);
00178 setupOkStateFromListSelection();
00179 }
00180
00181 void DashelConnectionDialog::serialGroupChecked()
00182 {
00183 netGroupBox->setChecked(false);
00184 serialGroupBox->setChecked(true);
00185 customGroupBox->setChecked(false);
00186 setupOkStateFromListSelection();
00187 }
00188
00189 void DashelConnectionDialog::customGroupChecked()
00190 {
00191 netGroupBox->setChecked(false);
00192 serialGroupBox->setChecked(false);
00193 customGroupBox->setChecked(true);
00194 setupOkStateFromListSelection();
00195 }
00196
00197 void DashelConnectionDialog::setupOkStateFromListSelection()
00198 {
00199 connectButton->setEnabled(serial->selectionModel()->hasSelection() || (!serialGroupBox->isChecked()));
00200 }
00201
00202
00203 DashelInterface::DashelInterface(QVector<QTranslator*> translators, const QString& commandLineTarget) :
00204 stream(0)
00205 {
00206
00207 DashelConnectionDialog targetSelector;
00208 if (!commandLineTarget.isEmpty())
00209 {
00210 bool failed = false;
00211 try
00212 {
00213 stream = Hub::connect(commandLineTarget.toStdString());
00214 }
00215 catch (DashelException e)
00216 {
00217
00218 failed = true;
00219 }
00220
00221 if (failed)
00222 QMessageBox::warning(0, tr("Connection to command line target failed"), tr("Cannot connect to target %0").arg(commandLineTarget));
00223 else
00224 return;
00225 }
00226
00227 while (true)
00228 {
00229 if (targetSelector.exec() == QDialog::Rejected)
00230 {
00231 throw std::runtime_error("connection dialog closed");
00232 }
00233
00234 try
00235 {
00236
00237 stream = Hub::connect(targetSelector.getTarget());
00238 assert(translators.size() == 2);
00239 language = targetSelector.getLocaleName();
00240 translators[0]->load(QString("qt_") + language, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
00241 translators[1]->load(QString(":/asebastudio_") + language);
00242 break;
00243 }
00244 catch (DashelException e)
00245 {
00246
00247 }
00248 }
00249 }
00250
00251
00252 void DashelInterface::run()
00253 {
00254 Dashel::Hub::run();
00255 }
00256
00257 void DashelInterface::incomingData(Stream *stream)
00258 {
00259 Message *message = Message::receive(stream);
00260 emit messageAvailable(message);
00261 }
00262
00263 void DashelInterface::connectionClosed(Stream* stream, bool abnormal)
00264 {
00265 Q_UNUSED(stream);
00266 Q_UNUSED(abnormal);
00267 emit dashelDisconnection();
00268 Q_ASSERT(stream == this->stream);
00269 this->stream = 0;
00270 }
00271
00272 void SignalingDescriptionsManager::nodeProtocolVersionMismatch(const std::string &nodeName, uint16 protocolVersion)
00273 {
00274 if (protocolVersion > ASEBA_PROTOCOL_VERSION)
00275 {
00276 QMessageBox::warning(0,
00277 QApplication::tr("Protocol version mismatch"),
00278 QApplication::tr("Aseba Studio uses an older protocol (%1) than node %0 (%2), please upgrade Aseba Studio.").arg(QString::fromUtf8(nodeName.c_str())).arg(ASEBA_PROTOCOL_VERSION).arg(protocolVersion)
00279 );
00280 }
00281 else if (protocolVersion < ASEBA_PROTOCOL_VERSION)
00282 {
00283 QMessageBox::warning(0,
00284 QApplication::tr("Protocol version mismatch"),
00285 QApplication::tr("Node %0 uses an older protocol (%2) than Aseba Studio (%1), please upgrade the node firmware.").arg(QString::fromUtf8(nodeName.c_str())).arg(ASEBA_PROTOCOL_VERSION).arg(protocolVersion)
00286 );
00287 }
00288 }
00289
00290 void SignalingDescriptionsManager::nodeDescriptionReceived(unsigned nodeId)
00291 {
00292 emit nodeDescriptionReceivedSignal(nodeId);
00293 }
00294
00295
00296 enum InNextState
00297 {
00298 NOT_IN_NEXT,
00299 WAITING_INITAL_PC,
00300 WAITING_LINE_CHANGE
00301 };
00302
00303 DashelTarget::Node::Node()
00304 {
00305 executionMode = EXECUTION_UNKNOWN;
00306 }
00307
00308 DashelTarget::DashelTarget(QVector<QTranslator*> translators, const QString& commandLineTarget) :
00309 dashelInterface(translators, commandLineTarget)
00310 {
00311 userEventsTimer.setSingleShot(true);
00312 connect(&userEventsTimer, SIGNAL(timeout()), SLOT(updateUserEvents()));
00313
00314
00315 connect(&dashelInterface, SIGNAL(messageAvailable(Message *)), SLOT(messageFromDashel(Message *)), Qt::QueuedConnection);
00316 connect(&dashelInterface, SIGNAL(dashelDisconnection()), SLOT(disconnectionFromDashel()), Qt::QueuedConnection);
00317
00318
00319 connect(&descriptionManager, SIGNAL(nodeDescriptionReceivedSignal(unsigned)), SLOT(nodeDescriptionReceived(unsigned)));
00320
00321 messagesHandlersMap[ASEBA_MESSAGE_DISCONNECTED] = &Aseba::DashelTarget::receivedDisconnected;
00322 messagesHandlersMap[ASEBA_MESSAGE_VARIABLES] = &Aseba::DashelTarget::receivedVariables;
00323 messagesHandlersMap[ASEBA_MESSAGE_ARRAY_ACCESS_OUT_OF_BOUNDS] = &Aseba::DashelTarget::receivedArrayAccessOutOfBounds;
00324 messagesHandlersMap[ASEBA_MESSAGE_DIVISION_BY_ZERO] = &Aseba::DashelTarget::receivedDivisionByZero;
00325 messagesHandlersMap[ASEBA_MESSAGE_EVENT_EXECUTION_KILLED] = &Aseba::DashelTarget::receivedEventExecutionKilled;
00326 messagesHandlersMap[ASEBA_MESSAGE_NODE_SPECIFIC_ERROR] = &Aseba::DashelTarget::receivedNodeSpecificError;
00327 messagesHandlersMap[ASEBA_MESSAGE_EXECUTION_STATE_CHANGED] = &Aseba::DashelTarget::receivedExecutionStateChanged;
00328 messagesHandlersMap[ASEBA_MESSAGE_BREAKPOINT_SET_RESULT] = &Aseba::DashelTarget::receivedBreakpointSetResult;
00329
00330
00331 GetDescription().serialize(dashelInterface.stream);
00332 dashelInterface.stream->flush();
00333 dashelInterface.start();
00334 }
00335
00336 DashelTarget::~DashelTarget()
00337 {
00338 dashelInterface.stop();
00339 dashelInterface.wait();
00340 DashelTarget::disconnect();
00341 }
00342
00343 void DashelTarget::disconnect()
00344 {
00345 if (dashelInterface.stream)
00346 {
00347
00348 for (NodesMap::const_iterator node = nodes.begin(); node != nodes.end(); ++node)
00349 {
00350
00351 BreakpointClearAll(node->first).serialize(dashelInterface.stream);
00352 Run(node->first).serialize(dashelInterface.stream);
00353 }
00354 dashelInterface.stream->flush();
00355 }
00356 }
00357
00358 const TargetDescription * const DashelTarget::getDescription(unsigned node) const
00359 {
00360 return descriptionManager.getDescription(node);
00361 }
00362
00363 void DashelTarget::uploadBytecode(unsigned node, const BytecodeVector &bytecode)
00364 {
00365 NodesMap::iterator nodeIt = nodes.find(node);
00366 assert(nodeIt != nodes.end());
00367
00368 nodeIt->second.debugBytecode = bytecode;
00369
00370 sendBytecode(dashelInterface.stream, node, std::vector<uint16>(bytecode.begin(), bytecode.end()));
00371
00372 dashelInterface.stream->flush();
00373 }
00374
00375 void DashelTarget::writeBytecode(unsigned node)
00376 {
00377 WriteBytecode(node).serialize(dashelInterface.stream);
00378 dashelInterface.stream->flush();
00379 }
00380
00381 void DashelTarget::reboot(unsigned node)
00382 {
00383 Reboot(node).serialize(dashelInterface.stream);
00384 dashelInterface.stream->flush();
00385 }
00386
00387 void DashelTarget::sendEvent(unsigned id, const VariablesDataVector &data)
00388 {
00389 UserMessage(id, data).serialize(dashelInterface.stream);
00390 dashelInterface.stream->flush();
00391 }
00392
00393 void DashelTarget::setVariables(unsigned node, unsigned start, const VariablesDataVector &data)
00394 {
00395 SetVariables(node, start, data).serialize(dashelInterface.stream);
00396 dashelInterface.stream->flush();
00397 }
00398
00399 void DashelTarget::getVariables(unsigned node, unsigned start, unsigned length)
00400 {
00401 unsigned variablesPayloadSize = (ASEBA_MAX_PACKET_SIZE - 4) / 2;
00402 while (length > variablesPayloadSize)
00403 {
00404 GetVariables(node, start, variablesPayloadSize).serialize(dashelInterface.stream);
00405 start += variablesPayloadSize;
00406 length -= variablesPayloadSize;
00407 }
00408 GetVariables(node, start, length).serialize(dashelInterface.stream);
00409 dashelInterface.stream->flush();
00410 }
00411
00412 void DashelTarget::reset(unsigned node)
00413 {
00414 Reset(node).serialize(dashelInterface.stream);
00415 dashelInterface.stream->flush();
00416 }
00417
00418 void DashelTarget::run(unsigned node)
00419 {
00420 NodesMap::iterator nodeIt = nodes.find(node);
00421 assert(nodeIt != nodes.end());
00422
00423 if (nodeIt->second.executionMode == EXECUTION_STEP_BY_STEP)
00424 Step(node).serialize(dashelInterface.stream);
00425 Run(node).serialize(dashelInterface.stream);
00426 dashelInterface.stream->flush();
00427 }
00428
00429 void DashelTarget::pause(unsigned node)
00430 {
00431 Pause(node).serialize(dashelInterface.stream);
00432 dashelInterface.stream->flush();
00433 }
00434
00435 void DashelTarget::next(unsigned node)
00436 {
00437 NodesMap::iterator nodeIt = nodes.find(node);
00438 assert(nodeIt != nodes.end());
00439
00440 nodeIt->second.steppingInNext = WAITING_INITAL_PC;
00441
00442 GetExecutionState getExecutionStateMessage;
00443 getExecutionStateMessage.dest = node;
00444
00445 getExecutionStateMessage.serialize(dashelInterface.stream);
00446 dashelInterface.stream->flush();
00447 }
00448
00449 void DashelTarget::stop(unsigned node)
00450 {
00451 Stop(node).serialize(dashelInterface.stream);
00452 dashelInterface.stream->flush();
00453 }
00454
00455 void DashelTarget::setBreakpoint(unsigned node, unsigned line)
00456 {
00457 int pc = getPCFromLine(node, line);
00458 if (pc >= 0)
00459 {
00460 BreakpointSet breakpointSetMessage;
00461 breakpointSetMessage.pc = pc;
00462 breakpointSetMessage.dest = node;
00463
00464 breakpointSetMessage.serialize(dashelInterface.stream);
00465 dashelInterface.stream->flush();
00466 }
00467 }
00468
00469 void DashelTarget::clearBreakpoint(unsigned node, unsigned line)
00470 {
00471 int pc = getPCFromLine(node, line);
00472 if (pc >= 0)
00473 {
00474 BreakpointClear breakpointClearMessage;
00475 breakpointClearMessage.pc = pc;
00476 breakpointClearMessage.dest = node;
00477
00478 breakpointClearMessage.serialize(dashelInterface.stream);
00479 dashelInterface.stream->flush();
00480 }
00481 }
00482
00483 void DashelTarget::clearBreakpoints(unsigned node)
00484 {
00485 BreakpointClearAll breakpointClearAllMessage;
00486 breakpointClearAllMessage.dest = node;
00487
00488 breakpointClearAllMessage.serialize(dashelInterface.stream);
00489 dashelInterface.stream->flush();
00490 }
00491
00492 void DashelTarget::updateUserEvents()
00493 {
00494
00495 if (userEventsQueue.size() > 20)
00496 emit userEventsDropped(userEventsQueue.size() - 20);
00497 while (userEventsQueue.size() > 20)
00498 {
00499 delete userEventsQueue.head();
00500 userEventsQueue.dequeue();
00501 }
00502
00503 while (!userEventsQueue.isEmpty())
00504 {
00505 emit userEvent(userEventsQueue.head()->type, userEventsQueue.head()->data);
00506 userEventsQueue.dequeue();
00507
00508 }
00509 }
00510
00511 void DashelTarget::messageFromDashel(Message *message)
00512 {
00513 bool deleteMessage = true;
00514
00515
00516
00517
00518 descriptionManager.processMessage(message);
00519
00520
00521 MessagesHandlersMap::const_iterator messageHandler = messagesHandlersMap.find(message->type);
00522 if (messageHandler == messagesHandlersMap.end())
00523 {
00524 UserMessage *userMessage = dynamic_cast<UserMessage *>(message);
00525 if (userMessage)
00526 {
00527 userEventsQueue.enqueue(userMessage);
00528 if (!userEventsTimer.isActive())
00529 userEventsTimer.start(50);
00530 deleteMessage = false;
00531 }
00532
00533
00534 }
00535 else
00536 {
00537 (this->*(messageHandler->second))(message);
00538 }
00539
00540
00541 if (deleteMessage)
00542 delete message;
00543 }
00544
00545 void DashelTarget::disconnectionFromDashel()
00546 {
00547 QMessageBox::critical(0, tr("Connection closed"), tr("Warning, connection closed, save your work and quit Studio."));
00548
00549
00550
00551 }
00552
00553 void DashelTarget::nodeDescriptionReceived(unsigned nodeId)
00554 {
00555 Node& node = nodes[nodeId];
00556
00557 node.steppingInNext = NOT_IN_NEXT;
00558 node.lineInNext = 0;
00559
00560 emit nodeConnected(nodeId);
00561 }
00562
00563 void DashelTarget::receivedVariables(Message *message)
00564 {
00565 Variables *variables = polymorphic_downcast<Variables *>(message);
00566
00567 emit variablesMemoryChanged(variables->source, variables->start, variables->variables);
00568 }
00569
00570 void DashelTarget::receivedArrayAccessOutOfBounds(Message *message)
00571 {
00572 ArrayAccessOutOfBounds *aa = polymorphic_downcast<ArrayAccessOutOfBounds *>(message);
00573
00574 int line = getLineFromPC(aa->source, aa->pc);
00575 if (line >= 0)
00576 {
00577 emit arrayAccessOutOfBounds(aa->source, line, aa->size, aa->index);
00578 emit executionModeChanged(aa->source, EXECUTION_STOP);
00579 }
00580 }
00581
00582 void DashelTarget::receivedDivisionByZero(Message *message)
00583 {
00584 DivisionByZero *dz = polymorphic_downcast<DivisionByZero *>(message);
00585
00586 int line = getLineFromPC(dz->source, dz->pc);
00587 if (line >= 0)
00588 {
00589 emit divisionByZero(dz->source, line);
00590 emit executionModeChanged(dz->source, EXECUTION_STOP);
00591 }
00592 }
00593
00594 void DashelTarget::receivedEventExecutionKilled(Message *message)
00595 {
00596 EventExecutionKilled *eek = polymorphic_downcast<EventExecutionKilled *>(message);
00597
00598 int line = getLineFromPC(eek->source, eek->pc);
00599 if (line >= 0)
00600 {
00601 emit eventExecutionKilled(eek->source, line);
00602 }
00603 }
00604
00605 void DashelTarget::receivedNodeSpecificError(Message *message)
00606 {
00607 NodeSpecificError *nse = polymorphic_downcast<NodeSpecificError *>(message);
00608
00609 int line = getLineFromPC(nse->source, nse->pc);
00610
00611
00612
00613 emit nodeSpecificError(nse->source, line, QString::fromUtf8(nse->message.c_str()));
00614 emit executionModeChanged(nse->source, EXECUTION_STOP);
00615
00616 }
00617
00618 void DashelTarget::receivedExecutionStateChanged(Message *message)
00619 {
00620 ExecutionStateChanged *ess = polymorphic_downcast<ExecutionStateChanged *>(message);
00621
00622 Node &node = nodes[ess->source];
00623 int line = getLineFromPC(ess->source, ess->pc);
00624
00625 Target::ExecutionMode mode;
00626
00627 if (ess->flags & ASEBA_VM_STEP_BY_STEP_MASK)
00628 {
00629 if (ess->flags & ASEBA_VM_EVENT_ACTIVE_MASK)
00630 {
00631 mode = EXECUTION_STEP_BY_STEP;
00632 if (line >= 0)
00633 {
00634
00635 if (node.steppingInNext == NOT_IN_NEXT)
00636 {
00637 emit executionPosChanged(ess->source, line);
00638 emit executionModeChanged(ess->source, mode);
00639 emit variablesMemoryEstimatedDirty(ess->source);
00640 }
00641 else if (node.steppingInNext == WAITING_INITAL_PC)
00642 {
00643
00644 node.lineInNext = line;
00645 node.steppingInNext = WAITING_LINE_CHANGE;
00646
00647 Step(ess->source).serialize(dashelInterface.stream);
00648 dashelInterface.stream->flush();
00649 }
00650 else if (node.steppingInNext == WAITING_LINE_CHANGE)
00651 {
00652 if (line != static_cast<int>(node.lineInNext))
00653 {
00654 node.steppingInNext = NOT_IN_NEXT;
00655 emit executionPosChanged(ess->source, line);
00656 emit executionModeChanged(ess->source, mode);
00657 emit variablesMemoryEstimatedDirty(ess->source);
00658 }
00659 else
00660 {
00661 Step(ess->source).serialize(dashelInterface.stream);
00662 dashelInterface.stream->flush();
00663 }
00664 }
00665 else
00666 assert(false);
00667
00668
00669 node.executionMode = mode;
00670 return;
00671 }
00672 }
00673 else
00674 {
00675 mode = EXECUTION_STOP;
00676 }
00677 }
00678 else
00679 {
00680 mode = EXECUTION_RUN;
00681 }
00682
00683 emit executionModeChanged(ess->source, mode);
00684 if (node.executionMode != mode)
00685 {
00686 emit variablesMemoryEstimatedDirty(ess->source);
00687 node.executionMode = mode;
00688 }
00689 }
00690
00691 void DashelTarget::receivedDisconnected(Message *message)
00692 {
00693 Disconnected *disconnected = polymorphic_downcast<Disconnected *>(message);
00694
00695 emit nodeDisconnected(disconnected->source);
00696 }
00697
00698 void DashelTarget::receivedBreakpointSetResult(Message *message)
00699 {
00700 BreakpointSetResult *bsr = polymorphic_downcast<BreakpointSetResult *>(message);
00701 unsigned node = bsr->source;
00702 emit breakpointSetResult(node, getLineFromPC(node, bsr->pc), bsr->success);
00703 }
00704
00705 int DashelTarget::getPCFromLine(unsigned node, unsigned line)
00706 {
00707
00708 NodesMap::const_iterator nodeIt = nodes.find(node);
00709
00710 if (nodeIt == nodes.end())
00711 return -1;
00712
00713
00714 for (size_t i = 0; i < nodeIt->second.debugBytecode.size(); i++)
00715 if (nodeIt->second.debugBytecode[i].line == line)
00716 return i;
00717
00718 return -1;
00719 }
00720
00721 int DashelTarget::getLineFromPC(unsigned node, unsigned pc)
00722 {
00723
00724 NodesMap::const_iterator nodeIt = nodes.find(node);
00725
00726 if (nodeIt == nodes.end())
00727 return -1;
00728
00729
00730 if (pc < nodeIt->second.debugBytecode.size())
00731 return nodeIt->second.debugBytecode[pc].line;
00732
00733 return -1;
00734 }
00735
00737 }