kumirprogram.cpp 20.8 KB
Newer Older
victor's avatar
 
victor committed
1
#include "kumirprogram.h"
victor's avatar
 
victor committed
2 3
#include "extensionsystem/pluginmanager.h"
#include "interfaces/actorinterface.h"
victor's avatar
 
victor committed
4
#include "dataformats/ast_algorhitm.h"
5
#include "interfaces/coursesinterface.h"
Victor Yacovlev's avatar
Victor Yacovlev committed
6
#include "widgets/iconprovider.h"
Victor Yacovlev's avatar
Victor Yacovlev committed
7
#include "widgets/actionproxy.h"
victor's avatar
 
victor committed
8 9 10

namespace CoreGUI {

victor's avatar
 
victor committed
11 12
using Shared::ActorInterface;
using namespace ExtensionSystem;
victor's avatar
 
victor committed
13 14 15

KumirProgram::KumirProgram(QObject *parent)
    : QObject(parent)
16
    , state_(Idle)
Victor Yacovlev's avatar
Victor Yacovlev committed
17
    , endStatus_(Running)
18 19 20 21 22 23 24 25 26 27
    , terminal_(0)
    , editor_(0)
    , mainWidget_(0)

    , blindRunAction_(0)
    , regularRunAction_(0)
    , testingRunAction_(0)
    , stepRunAction_(0)
    , stepInAction_(0)
    , stepOutAction_(0)
Victor Yacovlev's avatar
Victor Yacovlev committed
28
    , runToCursorAction_(0)
29
    , stopAction_(0)
Victor Yacovlev's avatar
Victor Yacovlev committed
30
    , toggleBreakpointAction_(0)
31
    , actions_(0)
Victor Yacovlev's avatar
Victor Yacovlev committed
32
    , breakpointActions_(0)
33
    , courseManagerRequest_(false)
victor's avatar
 
victor committed
34
{
35 36 37 38
    createActions();
    createConnections();
}

Victor Yacovlev's avatar
Victor Yacovlev committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
void KumirProgram::setEditorInstance(Shared::Editor::InstanceInterface *editor)
{
    using namespace Shared;
    editor_ = editor;
    toggleBreakpointAction_ = 0;
    if (breakpointActions_)
        breakpointActions_->deleteLater();
    breakpointActions_ = new QActionGroup(this);
    if (editor_ && runner() && runner()->hasBreakpointsSupport()) {
        if (editor_->toggleBreakpointAction()) {
            toggleBreakpointAction_ = new Widgets::ActionProxy(editor_->toggleBreakpointAction(), this);
        }
        toggleBreakpointAction_ = editor->toggleBreakpointAction();
        if (toggleBreakpointAction_) {
            breakpointActions_->addAction(toggleBreakpointAction_);
        }
    }
}

58 59 60 61

void KumirProgram::createActions()
{
    regularRunAction_ = new QAction(tr("Regular run"), this);
62
    regularRunAction_->setObjectName("run-regular");
63 64
    const QString qtcreatorIconsPath = ExtensionSystem::PluginManager::instance()->sharePath()
            + "/icons/from_qtcreator/";
Victor Yacovlev's avatar
Victor Yacovlev committed
65 66
//    regularRunAction_->setIcon(QIcon(qtcreatorIconsPath+"debugger_start.png"));
    regularRunAction_->setIcon(Widgets::IconProvider::self()->iconForName("run-regular"));
67
    connect(regularRunAction_, SIGNAL(triggered()), this, SLOT(regularRun()));
victor's avatar
 
victor committed
68
#ifndef Q_OS_MAC
69
    regularRunAction_->setShortcut(QKeySequence("F9"));
victor's avatar
 
victor committed
70
#else
Victor Yacovlev's avatar
Victor Yacovlev committed
71
    regularRunAction_->setShortcut(QKeySequence("F5"));
victor's avatar
 
victor committed
72
#endif
73
    regularRunAction_->setToolTip(regularRunAction_->text()+" <b>"+regularRunAction_->shortcut().toString()+"</b>");
victor's avatar
 
victor committed
74

75 76 77 78
    testingRunAction_ = new QAction(tr("Testing run"), this);
    connect(testingRunAction_, SIGNAL(triggered()), this, SLOT(testingRun()));
    testingRunAction_->setShortcut(QKeySequence("Ctrl+T"));
    testingRunAction_->setToolTip(testingRunAction_->text()+" <b>"+testingRunAction_->shortcut().toString()+"</b>");
victor's avatar
 
victor committed
79

80
    stepRunAction_ = new QAction(tr("Step over"), this);
81
    stepRunAction_->setObjectName("run-step-over");
Victor Yacovlev's avatar
Victor Yacovlev committed
82 83
//    stepRunAction_->setIcon(QIcon(qtcreatorIconsPath+"debugger_steponeproc_small.png"));
    stepRunAction_->setIcon(Widgets::IconProvider::self()->iconForName("run-step-over"));
84
    connect(stepRunAction_, SIGNAL(triggered()), this, SLOT(stepRun()));
victor's avatar
 
victor committed
85
#ifndef Q_OS_MAC
86
    stepRunAction_->setShortcut(QKeySequence("F8"));
victor's avatar
 
victor committed
87
#else
Victor Yacovlev's avatar
Victor Yacovlev committed
88
    stepRunAction_->setShortcut(QKeySequence("F6"));
victor's avatar
 
victor committed
89
#endif
90
    stepRunAction_->setToolTip(tr("Do big step")+" <b>"+stepRunAction_->shortcut().toString()+"</b>");
victor's avatar
 
victor committed
91

92
    stepInAction_ = new QAction(tr("Step in"), this);
93
    stepInAction_->setObjectName("run-step-in");
Victor Yacovlev's avatar
Victor Yacovlev committed
94 95
    stepInAction_->setIcon(Widgets::IconProvider::self()->iconForName("run-step-in"));
//    stepInAction_->setIcon(QIcon(qtcreatorIconsPath+"debugger_stepinto_small.png"));
96
    connect(stepInAction_, SIGNAL(triggered()), this, SLOT(stepIn()));
victor's avatar
 
victor committed
97
#ifndef Q_OS_MAC
98
    stepInAction_->setShortcut(QKeySequence("F7"));
victor's avatar
 
victor committed
99
#else
Victor Yacovlev's avatar
Victor Yacovlev committed
100
    stepInAction_->setShortcut(QKeySequence("F7"));
victor's avatar
 
victor committed
101
#endif
102
    stepInAction_->setToolTip(tr("Do small step")+" <b>"+stepInAction_->shortcut().toString()+"</b>");
victor's avatar
 
victor committed
103

104
    stepOutAction_ = new QAction(tr("Step to end"), this);
Victor Yacovlev's avatar
Victor Yacovlev committed
105 106 107
//    stepOutAction_->setObjectName("run-step-out");
    stepOutAction_->setIcon(Widgets::IconProvider::self()->iconForName("run-step-out"));
//    stepOutAction_->setIcon(QIcon(qtcreatorIconsPath+"debugger_stepoverproc_small.png"));
108
    connect(stepOutAction_, SIGNAL(triggered()), this, SLOT(stepOut()));
victor's avatar
 
victor committed
109
#ifndef Q_OS_MAC
110
    stepOutAction_->setShortcut(QKeySequence("Shift+F8"));
victor's avatar
 
victor committed
111
#else
Victor Yacovlev's avatar
Victor Yacovlev committed
112
    stepOutAction_->setShortcut(QKeySequence("Shift+F8"));
victor's avatar
 
victor committed
113
#endif
114
    stepOutAction_->setToolTip(tr("Run to end of algorhitm")+" <b>"+stepOutAction_->shortcut().toString()+"</b>");
victor's avatar
 
victor committed
115

Victor Yacovlev's avatar
Victor Yacovlev committed
116 117 118 119 120 121 122 123
    if (runner()->hasBreakpointsSupport()) {
        runToCursorAction_ = new QAction(tr("Run to cursor"), this);
        runToCursorAction_->setShortcut(QKeySequence("F4"));
        runToCursorAction_->setToolTip(tr("Run until the line editor cursor in")
                                       + "<b>" + runToCursorAction_->shortcut().toString() + "</b>");
        connect(runToCursorAction_, SIGNAL(triggered()), this, SLOT(runToCursor()));
    }

124
    stopAction_ = new QAction(tr("Stop"), this);
125
    stopAction_->setObjectName("run-stop");
Victor Yacovlev's avatar
Victor Yacovlev committed
126 127
//    stopAction_->setIcon(QIcon(qtcreatorIconsPath+"stop.png"));
    stopAction_->setIcon(Widgets::IconProvider::self()->iconForName("run-stop"));
128
    connect(stopAction_, SIGNAL(triggered()), this, SLOT(stop()));
victor's avatar
 
victor committed
129
#ifndef Q_OS_MAC
130
    stopAction_->setShortcut(QKeySequence("Esc"));
victor's avatar
 
victor committed
131
#else
Victor Yacovlev's avatar
Victor Yacovlev committed
132
    stopAction_->setShortcut(QKeySequence("Esc"));
victor's avatar
 
victor committed
133
#endif
134
    stopAction_->setToolTip(stopAction_->text()+" <b>"+stopAction_->shortcut().toString()+"</b>");
victor's avatar
 
victor committed
135

136 137 138
    stepInAction_->setEnabled(false);
    stepOutAction_->setEnabled(false);
    stopAction_->setEnabled(false);
victor's avatar
 
victor committed
139 140 141 142 143 144 145

    QAction * s1 = new QAction(this);
    s1->setSeparator(true);

    QAction * s2 = new QAction(this);
    s2->setSeparator(true);

victor's avatar
 
victor committed
146

147
    blindRunAction_ = new QAction(tr("Blind run"), this);
148
    blindRunAction_->setObjectName("run-blind");
Victor Yacovlev's avatar
Victor Yacovlev committed
149 150
    blindRunAction_->setIcon(Widgets::IconProvider::self()->iconForName("run-blind"));
//    blindRunAction_->setIcon(QIcon(qtcreatorIconsPath+"run.png"));
151
    connect(blindRunAction_, SIGNAL(triggered()), this, SLOT(blindRun()));
victor's avatar
 
victor committed
152
#ifndef Q_OS_MAC
153
    blindRunAction_->setShortcut(QKeySequence("Shift+F9"));
victor's avatar
 
victor committed
154 155

#else
Victor Yacovlev's avatar
Victor Yacovlev committed
156
    blindRunAction_->setShortcut(QKeySequence("Ctrl+R"));
victor's avatar
 
victor committed
157
#endif
158 159 160 161 162 163 164 165 166 167 168 169
    blindRunAction_->setToolTip(blindRunAction_->text()+" <b>"+blindRunAction_->shortcut().toString()+"</b>");


    actions_ = new QActionGroup(this);
    actions_->addAction(blindRunAction_);
    actions_->addAction(regularRunAction_);
    actions_->addAction(testingRunAction_);
    actions_->addAction(stopAction_);
    actions_->addAction(s1);
    actions_->addAction(stepRunAction_);
    actions_->addAction(stepInAction_);
    actions_->addAction(stepOutAction_);
Victor Yacovlev's avatar
Victor Yacovlev committed
170 171 172
    if (runToCursorAction_) {
        actions_->addAction(runToCursorAction_);
    }
173
}
victor's avatar
 
victor committed
174

175 176 177 178
Shared::RunInterface * KumirProgram::runner()
{
    using namespace ExtensionSystem;
    using namespace Shared;
victor's avatar
 
victor committed
179

180 181 182 183 184
    static RunInterface * RUNNER = nullptr;

    if (!RUNNER) {
        RUNNER = PluginManager::instance()->findPlugin<RunInterface>();
    }
victor's avatar
 
victor committed
185

186
    return RUNNER;
victor's avatar
 
victor committed
187 188
}

189
Shared::GeneratorInterface * KumirProgram::kumirCodeGenerator()
victor's avatar
 
victor committed
190
{
191 192 193 194 195 196
    using namespace ExtensionSystem;
    using namespace Shared;

    static GeneratorInterface * GENERATOR = nullptr;

    if (!GENERATOR) {
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
        GENERATOR = PluginManager::instance()->findPlugin<GeneratorInterface>("KumirCodeGenerator");
    }

    return GENERATOR;
}

Shared::GeneratorInterface * KumirProgram::kumirNativeGenerator()
{
    using namespace ExtensionSystem;
    using namespace Shared;

    static GeneratorInterface * GENERATOR = nullptr;

    if (!GENERATOR) {
        GENERATOR = PluginManager::instance()->findPlugin<GeneratorInterface>("LLVMCodeGenerator");
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
    }

    return GENERATOR;
}



void KumirProgram::createConnections()
{
    using namespace ExtensionSystem;
    using namespace Shared;

    KPlugin * run =
            PluginManager::instance()->findKPlugin<RunInterface>();

    connect(run, SIGNAL(stopped(int)),
            this, SLOT(handleRunnerStopped(int)));
    connect(run, SIGNAL(lineChanged(int,quint32,quint32)), this, SLOT(handleLineChanged(int,quint32,quint32)));
    connect(run, SIGNAL(marginText(int,QString)), this, SLOT(handleMarginTextRequest(int,QString)));
    connect(run, SIGNAL(clearMargin(int,int)), this, SLOT(handleMarginClearRequest(int,int)));
    connect(run, SIGNAL(replaceMarginText(int,QString, bool)),
            this, SLOT(handleMarginTextReplace(int,QString,bool)));
victor's avatar
 
victor committed
234 235
}

236 237 238
void KumirProgram::handleMarginTextReplace(int lineNo, const QString &text, bool redFgColor)
{
    if (lineNo!=-1 && !text.isEmpty())
239
        editor_->setMarginText(lineNo, text, redFgColor ? QColor("red") : QColor("black"));
240
}
victor's avatar
 
victor committed
241

victor's avatar
 
victor committed
242 243
void KumirProgram::handleMarginTextRequest(int lineNo, const QString &text)
{
victor's avatar
 
victor committed
244
    if (lineNo!=-1 && !text.isEmpty())
245
        editor_->appendMarginText(lineNo, text);
victor's avatar
 
victor committed
246 247 248 249
}

void KumirProgram::handleMarginClearRequest(int fromLine, int toLine)
{
250
    editor_->clearMarginText(fromLine, toLine);
victor's avatar
 
victor committed
251 252
}

victor's avatar
 
victor committed
253
void KumirProgram::setTerminal(Term *t, QDockWidget * w)
victor's avatar
 
victor committed
254
{
255 256
    using namespace ExtensionSystem;
    using namespace Shared;
257
    terminal_ = t;
Victor Yacovlev's avatar
Victor Yacovlev committed
258

Victor Yacovlev's avatar
Victor Yacovlev committed
259
    KPlugin * plugin_bytecodeRunObject =
260
            PluginManager::instance()->findKPlugin<RunInterface>();
Victor Yacovlev's avatar
Victor Yacovlev committed
261

262
    connect(terminal_, SIGNAL(inputFinished(QVariantList)),
Victor Yacovlev's avatar
Victor Yacovlev committed
263 264
            plugin_bytecodeRunObject, SIGNAL(finishInput(QVariantList)));
    connect(plugin_bytecodeRunObject, SIGNAL(inputRequest(QString)),
265
            terminal_, SLOT(input(QString)));
Victor Yacovlev's avatar
Victor Yacovlev committed
266
    connect(plugin_bytecodeRunObject, SIGNAL(outputRequest(QString)),
267
            terminal_, SLOT(output(QString)));
268
    connect(plugin_bytecodeRunObject, SIGNAL(errorOutputRequest(QString)),
269
            terminal_, SLOT(outputErrorStream(QString)));
victor's avatar
 
victor committed
270 271
}

victor's avatar
 
victor committed
272

victor's avatar
 
victor committed
273

victor's avatar
 
victor committed
274 275
void KumirProgram::blindRun()
{
276
    using namespace Shared;
Victor Yacovlev's avatar
Victor Yacovlev committed
277 278
    endStatusText_ = "";
    endStatus_ = Running;
279
    if (state_==Idle) {
victor's avatar
 
victor committed
280
        emit giveMeAProgram();
281
        prepareRunner(GeneratorInterface::LinesOnly);
victor's avatar
 
victor committed
282
    }
283
    state_ = BlindRun;
284
    PluginManager::instance()->switchGlobalState(PluginInterface::GS_Running);
285
    setAllActorsAnimationFlag(false);
286
    runner()->runBlind();
victor's avatar
 
victor committed
287 288
}

victor's avatar
 
victor committed
289 290
void KumirProgram::testingRun()
{
291
    using namespace Shared;
Victor Yacovlev's avatar
Victor Yacovlev committed
292 293
    endStatusText_ = "";
    endStatus_ = Running;
294
    if (state_==Idle) {
victor's avatar
 
victor committed
295
        emit giveMeAProgram();
296 297 298 299 300 301 302
        if (!prepareRunner(GeneratorInterface::LinesOnly)) {
            QMessageBox::information(mainWidget_, tr("No program loaded"),
                                  tr("You must open program first")
                                  );
            courseManagerRequest_ = false;
            return;
        }
303 304
        if (!runner()->hasTestingEntryPoint()) {
            QMessageBox::information(mainWidget_, testingRunAction_->text(),
victor's avatar
 
victor committed
305
                                  tr("This program does not have testing algorithm")
victor's avatar
 
victor committed
306
                                  );
307
            courseManagerRequest_ = false;
victor's avatar
 
victor committed
308 309 310
            return;
        }
    }
311
    state_ = TestingRun;
312
    PluginManager::instance()->switchGlobalState(PluginInterface::GS_Running);
313
    setAllActorsAnimationFlag(false);
314
    runner()->runTesting();
victor's avatar
 
victor committed
315 316
}

victor's avatar
 
victor committed
317
void KumirProgram::regularRun()
victor's avatar
 
victor committed
318
{
319
    using namespace Shared;
Victor Yacovlev's avatar
Victor Yacovlev committed
320 321
    endStatusText_ = "";
    endStatus_ = Running;
322
    if (state_==Idle) {
victor's avatar
 
victor committed
323
        emit giveMeAProgram();
324
        prepareRunner(GeneratorInterface::LinesAndVariables);
victor's avatar
 
victor committed
325
    }
326
    state_ = RegularRun;
327
    PluginManager::instance()->switchGlobalState(PluginInterface::GS_Running);
328
    setAllActorsAnimationFlag(true);
329
    runner()->runContinuous();
victor's avatar
 
victor committed
330 331
}

332
bool KumirProgram::prepareRunner(Shared::GeneratorInterface::DebugLevel debugLevel)
victor's avatar
 
victor committed
333
{
Victor Yacovlev's avatar
Victor Yacovlev committed
334 335
    using namespace Shared;

336
    bool ok = false;
337 338 339
    if (!editor_) {
        return false;
    }
340
    const QUrl sourceProgramUrl = editor_->documentContents().sourceUrl;
341
    QString sourceProgramPath;
Denis Khachko's avatar
Denis Khachko committed
342
    qDebug()<<sourceProgramUrl<<sourceProgramUrl.scheme()<<sourceProgramUrl.path();
343 344 345
    if (sourceProgramUrl.isLocalFile()) {
        sourceProgramPath = sourceProgramUrl.toLocalFile();
    }
Denis Khachko's avatar
Denis Khachko committed
346
    else if ("course" == sourceProgramUrl.scheme().toLower()) {
347 348
        sourceProgramPath = QDir::cleanPath(sourceProgramUrl.path());
    }
Victor Yacovlev's avatar
Victor Yacovlev committed
349
    RunInterface::RunnableProgram program;
350 351 352
    program.sourceFileName = sourceProgramPath;
    program.sourceData = editor_->analizer()->plugin()->sourceFileHandler()->toString(editor_->documentContents());

353 354
    runner()->setSourceHelper(editor_->analizer()->helper());

Victor Yacovlev's avatar
Victor Yacovlev committed
355 356 357 358
    if (runner()->hasBreakpointsSupport()) {
        runner()->removeAllBreakpoints();
    }

359
    if (editor_->analizer()->compiler()) {
360 361
        // Use AST to generate executable (only Kumir language)

362 363 364
        editor_->ensureAnalized();
        const AST::DataPtr ast = editor_->analizer()->compiler()->abstractSyntaxTree();
        QByteArray bufArray;
365

366 367
        kumirCodeGenerator()->setOutputToText(false);
        kumirCodeGenerator()->setDebugLevel(debugLevel);
368
        QString fileNameSuffix, mimeType;
Victor Yacovlev's avatar
Victor Yacovlev committed
369
        kumirCodeGenerator()->generateExecutable(ast, bufArray, mimeType, fileNameSuffix);
370 371 372

        program.executableData = bufArray;
        runner()->loadProgram(program);
373
    }
374 375 376 377 378 379 380 381
    else if (editor_->analizer()->externalToolchain()) {
        // Use external toolchain to make executable
        editor_->ensureAnalized();
        editor_->analizer()->externalToolchain()->prepareToRun(Shared::Analizer::RegularRun);
        program.executableFileName = editor_->analizer()->externalToolchain()->executableFilePath();
        program.sourceFileName = editor_->analizer()->externalToolchain()->debuggableSourceFileName();
        runner()->loadProgram(program);
    }
382
    else {
383 384 385 386 387
        // Use source text as executable
        program.executableData =editor_->analizer()->plugin()->sourceFileHandler()->toBytes(editor_->documentContents());
        program.executableFileName = program.sourceFileName;

        ok = runner()->loadProgram(program);
Victor Yacovlev's avatar
Victor Yacovlev committed
388
    }    
Victor Yacovlev's avatar
Victor Yacovlev committed
389 390 391 392 393 394 395 396
    if (program.sourceFileName.length() > 0) {
        const QString newCwd = QFileInfo(sourceProgramPath).absoluteDir().absolutePath();
        QDir::setCurrent(newCwd);
    }
    else {
        const QString newCwd = PluginManager::instance()->workspacePath();
        QDir::setCurrent(newCwd);
    }
Victor Yacovlev's avatar
Victor Yacovlev committed
397 398 399 400 401 402 403 404 405 406 407

    if (runner()->hasBreakpointsSupport()) {
        using Editor::Breakpoint;
        QList<Breakpoint> breaks = editor_->breakpoints();
        for (int i=0; i<breaks.size(); i++) {
            Breakpoint bp = breaks[i];
            bp.fileName = sourceProgramPath;
            runner()->insertOrChangeBreakpoint(bp.enabled, bp.fileName, bp.lineNo, bp.ignoreCount, bp.condition);
        }
    }

408
    terminal_->start(sourceProgramPath);
409
    return true;
victor's avatar
 
victor committed
410 411 412 413
}

void KumirProgram::stepRun()
{
414
    using namespace Shared;
Victor Yacovlev's avatar
Victor Yacovlev committed
415 416
    endStatusText_ = "";
    endStatus_ = Running;
417
    if (state_==Idle) {
victor's avatar
 
victor committed
418
        emit giveMeAProgram();
419
        prepareRunner(GeneratorInterface::LinesAndVariables);
victor's avatar
 
victor committed
420
    }
421
    state_ = StepRun;
Victor Yacovlev's avatar
Victor Yacovlev committed
422
//    stepRunAction_->setIcon(QIcon::fromTheme("debug-step-over",  QIcon(QApplication::instance()->property("sharePath").toString()+"/icons/debug-step-over.png")));
423
    PluginManager::instance()->switchGlobalState(PluginInterface::GS_Running);
424
    setAllActorsAnimationFlag(false);
425
    runner()->runStepOver();
victor's avatar
 
victor committed
426 427 428 429
}

void KumirProgram::stepIn()
{
430
    if (state_!=StepRun) {
victor's avatar
 
victor committed
431 432 433
        stepRun();
    }
    else {
434
        setAllActorsAnimationFlag(true);
435
        runner()->runStepInto();
victor's avatar
 
victor committed
436
    }
victor's avatar
 
victor committed
437 438 439 440
}

void KumirProgram::stepOut()
{
441
    if (state_!=StepRun)
victor's avatar
 
victor committed
442
        return;
443
    setAllActorsAnimationFlag(true);
444
    runner()->runToEnd();
victor's avatar
 
victor committed
445 446
}

Victor Yacovlev's avatar
Victor Yacovlev committed
447 448 449 450 451 452 453 454 455 456 457 458 459 460
void KumirProgram::runToCursor()
{
    using namespace Shared;
    if (state_==Idle) {
        emit giveMeAProgram();
        prepareRunner(GeneratorInterface::LinesAndVariables);
        state_ = RegularRun;
    }
    const quint32 currentLineNumber = editorInstance()->currentLineNumber();
    const QString sourceProgramPath = editor_->documentContents().sourceUrl.toLocalFile();
    runner()->insertSingleHitBreakpoint(sourceProgramPath, currentLineNumber);
    regularRun();
}

victor's avatar
 
victor committed
461 462
void KumirProgram::stop()
{
463 464
    if (state_==StepRun || state_==RegularRun || state_==TestingRun || state_==BlindRun) {
        runner()->terminate();
465
    }    
victor's avatar
 
victor committed
466
}
victor's avatar
 
victor committed
467

victor's avatar
 
victor committed
468

469 470 471 472 473 474 475 476 477 478 479 480 481
void KumirProgram::setAllActorsAnimationFlag(bool animationEnabled)
{
    QList<KPlugin*> actorPlugins = ExtensionSystem::PluginManager::instance()
            ->loadedPlugins("Actor*");
    foreach (KPlugin * plugin , actorPlugins) {
        Shared::ActorInterface * actor =
                qobject_cast<Shared::ActorInterface*>(plugin);
        if (actor) {
            actor->setAnimationEnabled(animationEnabled);
        }
    }
}

victor's avatar
 
victor committed
482 483
void KumirProgram::handleRunnerStopped(int rr)
{
484
    using namespace Shared;
485
    const State previousState = state_;
486 487 488
    RunInterface::StopReason reason = RunInterface::StopReason (rr);
    if (reason==RunInterface::SR_InputRequest) {
        PluginManager::instance()->switchGlobalState(PluginInterface::GS_Input);
victor's avatar
 
victor committed
489
    }
490 491
    else if (reason==RunInterface::SR_UserInteraction) {
        PluginManager::instance()->switchGlobalState(PluginInterface::GS_Pause);
victor's avatar
 
victor committed
492 493
//        a_stepIn->setEnabled(plugin_bytecodeRun->canStepInto());
//        a_stepOut->setEnabled(plugin_bytecodeRun->canStepOut());
victor's avatar
 
victor committed
494
    }
495
    else if (reason==RunInterface::SR_UserTerminated) {
Victor Yacovlev's avatar
Victor Yacovlev committed
496 497
        endStatusText_ = tr("Evaluation terminated");
        endStatus_ = Terminated;
498
        terminal_->finish();
499
        PluginManager::instance()->switchGlobalState(PluginInterface::GS_Observe);
500 501 502
        state_ = Idle;
        terminal_->clearFocus();
        editor_->unhighlightLine();
victor's avatar
 
victor committed
503
    }
504
    else if (reason==RunInterface::SR_Error) {
Victor Yacovlev's avatar
Victor Yacovlev committed
505 506
        endStatusText_ = tr("Evaluation error");
        endStatus_ = Exception;
507 508
        terminal_->error(runner()->error());
        editor_->highlightLineRed(runner()->currentLineNo(), runner()->currentColumn().first, runner()->currentColumn().second);
509
        PluginManager::instance()->switchGlobalState(PluginInterface::GS_Observe);
510 511
        state_ = Idle;
        terminal_->clearFocus();
victor's avatar
 
victor committed
512
    }
513
    else if (reason==RunInterface::SR_Done) {
Victor Yacovlev's avatar
Victor Yacovlev committed
514 515
        endStatusText_ = tr("Evaluation finished");
        endStatus_ = Finished;
516
        terminal_->finish();
517
        PluginManager::instance()->switchGlobalState(PluginInterface::GS_Observe);
518 519 520
        state_ = Idle;
        terminal_->clearFocus();
        editor_->unhighlightLine();
victor's avatar
 
victor committed
521
    }
victor's avatar
 
victor committed
522

523
    typedef CoursesInterface CI;
524 525
    CI * courseManager =
            ExtensionSystem::PluginManager::instance()->findPlugin<CI>();
526
    typedef RunInterface RI;
527 528
    RI * runner =
            ExtensionSystem::PluginManager::instance()->findPlugin<RI>();
Victor Yacovlev's avatar
Victor Yacovlev committed
529
    if (courseManager && /*runner->isTestingRun() &&*/ courseManagerRequest_) {
530 531 532 533 534 535 536 537 538 539
        if (reason == Shared::RunInterface::SR_UserTerminated) {
            courseManager->setTestingResult(CI::UserTerminated, 0);
        }
        else if (reason == Shared::RunInterface::SR_Done) {
            courseManager->setTestingResult(CI::SuccessfullyFinished,
                                            runner->valueStackTopItem().toInt());
        }
        else if (reason == Shared::RunInterface::SR_Error) {
            courseManager->setTestingResult(CI::AbortedOnError, 0);
        }
victor's avatar
 
victor committed
540 541
    }

victor's avatar
 
victor committed
542 543
}

544
void KumirProgram::handleLineChanged(int lineNo, quint32 colStart, quint32 colEnd)
victor's avatar
 
victor committed
545 546
{
    if (lineNo!=-1) {
547 548
        if (runner()->error().isEmpty())
            editor_->highlightLineGreen(lineNo, colStart, colEnd);
victor's avatar
 
victor committed
549
        else
550
            editor_->highlightLineRed(lineNo, colStart, colEnd);
victor's avatar
 
victor committed
551 552
    }
    else {
553
        editor_->unhighlightLine();
victor's avatar
 
victor committed
554 555
    }
}
victor's avatar
 
victor committed
556 557


victor's avatar
 
victor committed
558
void KumirProgram::switchGlobalState(GlobalState prev, GlobalState cur)
victor's avatar
 
victor committed
559
{
560 561
    using Shared::PluginInterface;
    if (cur==PluginInterface::GS_Unlocked || cur==PluginInterface::GS_Observe) {
562

563 564 565 566
        blindRunAction_->setEnabled(true);
        regularRunAction_->setEnabled(true);
        testingRunAction_->setEnabled(true);
        stepRunAction_->setEnabled(true);
victor's avatar
 
victor committed
567 568
//        a_stepRun->setText(tr("Step run"));
//        a_stepRun->setIcon(QIcon::fromTheme("media-skip-forward", QIcon(QApplication::instance()->property("sharePath").toString()+"/icons/media-skip-forward.png")));
569 570 571
        stepInAction_->setEnabled(true);
        stepOutAction_->setEnabled(false);
        stopAction_->setEnabled(false);
victor's avatar
 
victor committed
572

victor's avatar
 
victor committed
573
    }
574
    if (cur==PluginInterface::GS_Running || cur==PluginInterface::GS_Input) {
575

576 577 578 579 580 581 582
        blindRunAction_->setEnabled(false);
        regularRunAction_->setEnabled(false);
        testingRunAction_->setEnabled(false);
        stepRunAction_->setEnabled(false);
        stepInAction_->setEnabled(false);
        stepOutAction_->setEnabled(false);
        stopAction_->setEnabled(true);
victor's avatar
 
victor committed
583
    }
584
    if (cur==PluginInterface::GS_Pause) {
585

586 587 588 589
        blindRunAction_->setEnabled(true);
        regularRunAction_->setEnabled(true);
        stepRunAction_->setEnabled(true);
        testingRunAction_->setEnabled(false);
victor's avatar
 
victor committed
590 591
//        a_stepRun->setText(tr("Step over"));
//        a_stepRun->setIcon(QIcon::fromTheme("debug-step-over", QIcon(QApplication::instance()->property("sharePath").toString()+"/icons/debug-step-over.png")));
592 593 594
        stepInAction_->setEnabled(true);
        stepOutAction_->setEnabled(true);
        stopAction_->setEnabled(true);
victor's avatar
 
victor committed
595 596 597
    }
}

victor's avatar
 
victor committed
598
} // namespace CoreGui