File indexing completed on 2024-04-21 03:45:29

0001 /*
0002     SPDX-FileCopyrightText: 2003-2009 Cies Breijs <cies AT kde DOT nl>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "mainwindow.h"
0008 
0009 #include <QDebug>
0010 #include <QDir>
0011 #include <QFileInfo>
0012 #include <QFileDialog>
0013 #include <QInputDialog>
0014 #include <QLabel>
0015 #include <QMenu>
0016 #include <QPointer>
0017 #include <QPrintDialog>
0018 #include <QPrinter>
0019 #include <QSaveFile>
0020 #include <QStackedWidget>
0021 #include <QStandardPaths>
0022 #include <QStatusBar>
0023 #include <QTimer>
0024 #include <QActionGroup>
0025 #include <QHBoxLayout>
0026 
0027 #include <KActionCollection>
0028 #include <KConfigGroup>
0029 #include <KHelpClient>
0030 #include <KLocalizedString>
0031 #include <KMessageBox>
0032 #include <KRecentFilesAction>
0033 #include <KSharedConfig>
0034 #include <KNSWidgets/Action>
0035 #include "interpreter/errormsg.h"
0036 #include "interpreter/translator.h"
0037 
0038 
0039 static const int MARGIN_SIZE = 3;  // defaultly styled margins look shitty
0040 static const char* const GHNS_TARGET = "kturtle/examples";
0041 
0042 MainWindow::MainWindow()
0043 {
0044     setupDockWindows();  // the setup order matters
0045     setupActions();
0046     setupCanvas();
0047     setupInterpreter();
0048     setupEditor();
0049     setupStatusBar();
0050 
0051     iterationTimer = new QTimer(this);
0052     connect(iterationTimer, &QTimer::timeout, this, &MainWindow::iterate);
0053 
0054     connect(editor, &Editor::contentChanged, inspector, &Inspector::disable);
0055     connect(editor, &Editor::contentChanged, errorDialog, &ErrorDialog::disable);
0056 
0057     connect(errorDialog, &ErrorDialog::currentlySelectedError, editor, &Editor::markCurrentError);
0058 
0059     colorPicker = nullptr;
0060 
0061     statusBar()->showMessage(i18nc("@info:status the application is ready for commands", "Ready"));
0062     updateContentName();  // also sets the window caption to 'untitled'
0063     setRunSpeed(1);  // full speed with highlighting
0064     abort();  // sets the run-states for the actions right
0065 
0066     setupGUI();
0067 
0068     // after all is set up:
0069     readConfig();
0070     updateLanguagesMenu();
0071     
0072     currentlyRunningConsole = false;
0073 }
0074 
0075 MainWindow::~MainWindow()
0076 {
0077     delete editor;
0078     KSharedConfig::openConfig()->sync();
0079 }
0080 
0081 void MainWindow::closeEvent(QCloseEvent *event)
0082 {
0083     if (editor->maybeSave()) {
0084         event->accept();
0085         writeConfig();
0086     } else {
0087         event->ignore();
0088     }
0089 }
0090 
0091 void MainWindow::filePrintDialog()
0092 {
0093     QPrinter printer;
0094     QPointer<QPrintDialog> printDialog = new QPrintDialog(&printer, this);
0095     if (printDialog->exec()) {
0096         QPainter painter;
0097         painter.begin(&printer);
0098         editor->document()->drawContents(&painter);
0099         painter.end();
0100     }
0101     delete printDialog;
0102 }
0103 
0104 void MainWindow::canvasPrintDialog()
0105 {
0106     QPrinter printer;
0107     QPointer<QPrintDialog> printDialog = new QPrintDialog(&printer, this);
0108     if (printDialog->exec()) {
0109         QPainter painter;
0110         painter.begin(&printer);
0111         canvas->scene()->render(&painter);
0112         painter.end();
0113     }
0114     delete printDialog;
0115 }
0116 
0117 void MainWindow::showDirectionDialog()
0118 {
0119     directionDialog = new DirectionDialog(canvas->turtleAngle(), this);
0120     connect(directionDialog, &DirectionDialog::pasteText, editor, &Editor::insertPlainText);
0121 }
0122 void MainWindow::showColorPicker()
0123 {
0124     if (!colorPicker) {
0125         colorPicker = new ColorPicker(this);
0126         connect(colorPicker, &ColorPicker::pasteText, editor, &Editor::insertPlainText);
0127     }
0128     colorPicker->show();
0129 }
0130 
0131 
0132 void MainWindow::contextHelp()
0133 {
0134   KHelpClient::invokeHelp(contextHelpAnchor);
0135 }
0136 
0137 /*void MainWindow::whatsThis()
0138 {
0139     QWhatsThis::enterWhatsThisMode();
0140 }*/
0141 
0142 void MainWindow::documentWasModified()
0143 {
0144 //TODO remove this function or make it do something
0145 //  setWindowModified(textEdit->document()->isModified());
0146 }
0147 
0148 void MainWindow::setRunSpeed(int speed)
0149 {
0150     switch (speed) {
0151         case 0: dedicatedSpeedAct->setChecked(true); break;
0152         case 1: fullSpeedAct->setChecked(true);      break;
0153         case 2: slowSpeedAct->setChecked(true);      break;
0154         case 3: slowerSpeedAct->setChecked(true);    break;
0155         case 4: slowestSpeedAct->setChecked(true);   break;
0156         case 5: stepSpeedAct->setChecked(true);      break;
0157     }
0158     //TODO runOptionBox->setCurrentIndex(speed);
0159     runSpeed = speed;
0160 }
0161 
0162 void MainWindow::setupActions()
0163 {
0164     QAction * a;
0165     KActionCollection* ac = actionCollection();
0166 
0167     // WHAT IS THIS?
0168     // Similar to a status tip, but not the same.
0169     // A status tip is displayed on hover, a whatisthis is displayed when
0170     // an item is clicked on it whatisthis mode  (cies doesn't like whatis mode for every little widget)
0171     // (he thinks whatis is to give the translators even more work)
0172 
0173     // File menu actions
0174     a = actionCollection()->addAction(KStandardAction::New,  QStringLiteral("file_new"), editor, SLOT(newFile()));
0175     a->setStatusTip(i18n("Create a new file"));
0176     a->setWhatsThis(i18n("New File: Create a new file"));
0177 
0178     a = actionCollection()->addAction(KStandardAction::Open,  QStringLiteral("file_open"), editor, SLOT(openFile()));
0179     a->setStatusTip(i18n("Open an existing file"));
0180     a->setWhatsThis(i18n("Open File: Open an existing file"));
0181 
0182     //TODO: Is this correct? -- It doesn't seem to be working
0183     recentFilesAction = dynamic_cast<KRecentFilesAction*>(actionCollection()->addAction(KStandardAction::OpenRecent,  QStringLiteral("file_recent"), editor, SLOT(openFile(QUrl))));
0184     recentFilesAction->setStatusTip(i18n("Open a recently used file"));
0185     recentFilesAction->setWhatsThis(i18n("Open Recent File: Open a recently used file"));
0186 
0187     auto knsa = new KNSWidgets::Action(i18n("Get more examples..."), QStringLiteral("kturtle.knsrc"), this);
0188     actionCollection()->addAction(QStringLiteral("get_new_examples"), knsa);
0189     connect(knsa, &KNSWidgets::Action::dialogFinished, this, [this] (const QList<KNSCore::Entry> &changedEntries) {
0190         if (!changedEntries.isEmpty()) {
0191             updateExamplesMenu();
0192         }
0193     });
0194 
0195     a = actionCollection()->addAction(KStandardAction::Save,  QStringLiteral("file_save"), editor, SLOT(saveFile()));
0196     a->setStatusTip(i18n("Save the current file to disk"));
0197     a->setWhatsThis(i18n("Save File: Save the current file to disk"));
0198     connect(editor->document(), &QTextDocument::modificationChanged, a, &QAction::setEnabled);
0199 
0200     a = actionCollection()->addAction(KStandardAction::SaveAs,  QStringLiteral("file_save_as"), editor, SLOT(saveFileAs()));
0201     a->setStatusTip(i18n("Save the current file under a different name"));
0202     a->setWhatsThis(i18n("Save File As: Save the current file under a different name"));
0203 
0204     exportToHtmlAct = actionCollection()->addAction(QStringLiteral("file_export_to_html"));
0205     exportToHtmlAct->setText(i18n("Export to &HTML..."));
0206     exportToHtmlAct->setStatusTip(i18n("Export the contents of the editor as HTML"));
0207     exportToHtmlAct->setWhatsThis(i18n("Export to HTML: Export the contents of the editor as HTML"));
0208     connect(exportToHtmlAct, &QAction::triggered, this, &MainWindow::exportToHtml);
0209 
0210     a = actionCollection()->addAction(KStandardAction::Print, QStringLiteral("file_print"), this, SLOT(filePrintDialog()));
0211     a->setStatusTip(i18n("Print the code"));
0212     a->setWhatsThis(i18n("Print: Print the code"));
0213 
0214     a = actionCollection()->addAction(KStandardAction::Quit, QStringLiteral("file_quit"), this, SLOT(close()));
0215     a->setStatusTip(i18n("Quit KTurtle"));
0216     a->setWhatsThis(i18n("Quit: Quit KTurtle"));
0217 
0218     // Edit menu actions
0219     a = KStandardAction::undo(editor->view(), SLOT(undo()), ac);
0220     a->setStatusTip(i18n("Undo a change in the editor"));
0221     a->setWhatsThis(i18n("Undo: Undo a change in the editor"));
0222     a->setEnabled(false);
0223     connect(editor->view(), &QTextEdit::undoAvailable, a, &QAction::setEnabled);
0224 
0225     a = KStandardAction::redo(editor->view(), SLOT(redo()), ac);
0226     a->setStatusTip(i18n("Redo a previously undone change in the editor"));
0227     a->setWhatsThis(i18n("Redo: Redo a previously undone change in the editor"));
0228     a->setEnabled(false);
0229     connect(editor->view(), &QTextEdit::redoAvailable, a, &QAction::setEnabled);
0230 
0231     a = KStandardAction::cut(editor->view(), SLOT(cut()), ac);
0232     a->setStatusTip(i18n("Cut the selected text to the clipboard"));
0233     a->setWhatsThis(i18n("Cut: Cut the selected text to the clipboard"));
0234     a->setEnabled(false);
0235     connect(editor->view(), &QTextEdit::copyAvailable, a, &QAction::setEnabled);
0236 
0237     a = KStandardAction::copy(editor->view(), SLOT(copy()), ac);
0238     a->setStatusTip(i18n("Copy the selected text to the clipboard"));
0239     a->setWhatsThis(i18n("Copy: Copy the selected text to the clipboard"));
0240     a->setEnabled(false);
0241     connect(editor->view(), &QTextEdit::copyAvailable, a, &QAction::setEnabled);
0242 
0243     a = KStandardAction::paste(editor->view(), SLOT(paste()), ac);
0244     a->setStatusTip(i18n("Paste the clipboard's content into the current selection"));
0245     a->setWhatsThis(i18n("Paste: Paste the clipboard's content into the current selection"));
0246 
0247     a = KStandardAction::selectAll(editor->view(), SLOT(selectAll()), ac);
0248     a->setStatusTip(i18n("Select all the code in the editor"));
0249     a->setWhatsThis(i18n("Select All: Select all the code in the editor"));
0250     a->setEnabled(true);
0251 
0252     a  = new QAction(i18n("Overwrite Mode"), this);
0253     actionCollection()->addAction(QStringLiteral("overwrite"), a );
0254     a->setStatusTip(i18n("Toggle between the 'insert' and 'overwrite' mode"));
0255     a->setWhatsThis(i18n("Overwrite Mode: Toggle between the 'insert' and 'overwrite' mode"));
0256     actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::Key_Insert));
0257     a->setCheckable(true);
0258     a->setChecked(false);
0259     connect(a, &QAction::toggled, this, &MainWindow::toggleOverwriteMode);
0260 
0261     a = KStandardAction::find(editor, SLOT(find()), ac);
0262     a->setStatusTip(i18n("Search through the code in the editor"));
0263     a->setWhatsThis(i18n("Find: Search through the code in the editor"));
0264 
0265     a = KStandardAction::findNext(editor, SLOT(findNext()), ac);
0266     a->setStatusTip(i18n("Continue searching through the code in the editor"));
0267     a->setWhatsThis(i18n("Find Next: Continue searching through the code in the editor"));
0268 
0269     a = KStandardAction::findPrev(editor, SLOT(findPrev()), ac);
0270     a->setStatusTip(i18n("Continue searching backwards through the code in the editor"));
0271     a->setWhatsThis(i18n("Find Previous: Continue searching backwards through the code in the editor"));
0272 
0273     //TODO: Implement search/replace
0274     //a = KStandardAction::replace(editor, SLOT(replace()), ac);
0275     //a->setStatusTip(i18n("Search and replace"));
0276     //a->setWhatsThis(i18n("Replace: Replace text in the editor"));
0277 
0278     // Canvas menu action
0279     exportToPngAct = actionCollection()->addAction(QStringLiteral("canvas_export_to_png"));
0280     exportToPngAct->setText(i18n("Export to &Image (PNG)..."));
0281     exportToPngAct->setStatusTip(i18n("Export the current canvas to a PNG raster image"));
0282     exportToPngAct->setWhatsThis(i18n("Export to PNG: Export the current canvas to a PNG raster image"));
0283     connect(exportToPngAct, &QAction::triggered, this, &MainWindow::exportToPng);
0284 
0285     exportToSvgAct = actionCollection()->addAction(QStringLiteral("canvas_export_to_svg"));
0286     exportToSvgAct->setText(i18n("Export to &Drawing (SVG)..."));
0287     exportToSvgAct->setStatusTip(i18n("Export the current canvas to Scalable Vector Graphics"));
0288     exportToSvgAct->setWhatsThis(i18n("Export to SVG: Export the current canvas to Scalable Vector Graphics"));
0289     connect(exportToSvgAct, &QAction::triggered, this, &MainWindow::exportToSvg);
0290 
0291     printCanvasAct = new QAction(QIcon::fromTheme(QStringLiteral("document-print")), i18n("&Print Canvas..."), this);
0292     actionCollection()->addAction(QStringLiteral("canvas_print"), printCanvasAct);
0293     printCanvasAct->setStatusTip(i18n("Print the canvas"));
0294     printCanvasAct->setWhatsThis(i18n("Print: Print the canvas"));
0295     connect(printCanvasAct, &QAction::triggered, this, &MainWindow::canvasPrintDialog);
0296 
0297     // Run menu actions
0298     runAct = new QAction(QIcon::fromTheme(QStringLiteral("media-playback-start")), i18n("&Run"), this);
0299     actionCollection()->addAction(QStringLiteral("run"), runAct);
0300     actionCollection()->setDefaultShortcut(runAct, QKeySequence(Qt::Key_F5));
0301     runAct->setStatusTip(i18n("Execute the program"));
0302     runAct->setWhatsThis(i18n("Run: Execute the program"));
0303     connect(runAct, &QAction::triggered, this, &MainWindow::run);
0304 
0305     pauseAct = new QAction(QIcon::fromTheme(QStringLiteral("media-playback-pause")), i18n("&Pause"), this);
0306     actionCollection()->addAction(QStringLiteral("pause"), pauseAct);
0307     pauseAct->setCheckable(true);
0308     actionCollection()->setDefaultShortcut(pauseAct, QKeySequence(Qt::Key_F6));
0309     pauseAct->setStatusTip(i18n("Pause execution"));
0310     pauseAct->setWhatsThis(i18n("Pause: Pause execution"));
0311     connect(pauseAct, &QAction::triggered, this, &MainWindow::pause);
0312 
0313     abortAct = new QAction(QIcon::fromTheme(QStringLiteral("process-stop")), i18n("&Abort"), this);
0314     actionCollection()->addAction(QStringLiteral("abort"), abortAct);
0315     actionCollection()->setDefaultShortcut(abortAct, QKeySequence(Qt::Key_F7));
0316     abortAct->setStatusTip(i18n("Stop executing program"));
0317     abortAct->setWhatsThis(i18n("Abort: Stop executing program"));
0318     connect(abortAct, &QAction::triggered, this, &MainWindow::abort);
0319 
0320 //  new QAction(i18n("&Indent"), "format-indent-more", CTRL+Key_I, this, SLOT(slotIndent()), ac, "edit_indent");
0321 //  new QAction(i18n("&Unindent"), "format-indent-less", CTRL+SHIFT+Key_I, this, SLOT(slotUnIndent()), ac, "edit_unindent");
0322 //  new QAction(i18n("Cl&ean Indentation"), 0, 0, this, SLOT(slotCleanIndent()), ac, "edit_cleanIndent");
0323 //  new QAction(i18n("Co&mment"), 0, CTRL+Key_D, this, SLOT(slotComment()), ac, "edit_comment");
0324 //  new QAction(i18n("Unc&omment"), 0, CTRL+SHIFT+Key_D, this, SLOT(slotUnComment()), ac, "edit_uncomment");
0325 
0326     // Tools menu actions
0327     a = new QAction(i18n("&Direction Chooser..."), this);
0328     actionCollection()->addAction(QStringLiteral("direction_chooser"), a);
0329     a->setStatusTip(i18n("Shows the direction chooser dialog"));
0330     a->setWhatsThis(i18n("Direction Chooser: Show the direction chooser dialog"));
0331     connect(a, &QAction::triggered, this, &MainWindow::showDirectionDialog);
0332 
0333     a = new QAction(i18n("&Color Picker..."), this);
0334     actionCollection()->addAction(QStringLiteral("color_picker"), a);
0335     a->setStatusTip(i18n("Shows the color picker dialog"));
0336     a->setWhatsThis(i18n("Color Picker: Show the color picker dialog"));
0337     connect(a, &QAction::triggered, this, &MainWindow::showColorPicker);
0338 
0339     // Settings menu action
0340     a = new QAction(i18n("Show &Editor"), this);
0341     actionCollection()->addAction(QStringLiteral("show_editor"), a);
0342     a->setStatusTip(i18n("Show or hide the Code Editor"));
0343     a->setWhatsThis(i18n("Show Code Editor: Show or hide the Code Editor"));
0344     actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::CTRL | Qt::Key_E));
0345     a->setCheckable(true);
0346     a->setChecked(true);
0347     connect(a, &QAction::toggled, editorDock, &LocalDockWidget::setVisible);
0348     connect(editorDock, &LocalDockWidget::visibilityChanged, a, &QAction::setChecked);
0349 
0350     a = new QAction(i18n("Show &Inspector"), this);
0351     actionCollection()->addAction(QStringLiteral("show_inspector"), a);
0352     a->setStatusTip(i18n("Show or hide the Inspector"));
0353     a->setWhatsThis(i18n("Show Inspector: Show or hide the Inspector"));
0354     actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::CTRL | Qt::Key_I));
0355     a->setCheckable(true);
0356     a->setChecked(true);
0357     connect(a, &QAction::toggled, inspectorDock, &LocalDockWidget::setVisible);
0358     connect(inspectorDock, &LocalDockWidget::visibilityChanged, a, &QAction::setChecked);
0359 
0360     a = new QAction(i18n("Show E&rrors"), this);
0361     actionCollection()->addAction(QStringLiteral("show_errors"), a);
0362     a->setStatusTip(i18n("Show or hide the Errors tab"));
0363     a->setWhatsThis(i18n("Show Errors: Show or hide the Errors tab"));
0364     a->setCheckable(true);
0365     a->setChecked(false);
0366     connect(a, &QAction::toggled, this, &MainWindow::showErrorDialog);
0367         
0368 //  a = new QAction(i18n("Show &Console"), this);
0369 //  actionCollection()->addAction("show_console", a);
0370 //  a->setStatusTip(i18n("Show or hide the interactive Console tab"));
0371 //  a->setWhatsThis(i18n("Show Console: Show or hide the interactive Console tab"));
0372 //  a->setCheckable(true);
0373 //  a->setChecked(false);
0374 //  connect(a, SIGNAL(toggled(bool)), consoleDock, SLOT(setVisible(bool)));
0375 //  connect(consoleDock, SIGNAL(visibilityChanged(bool)), a, SLOT(setChecked(bool)));
0376 
0377     a = new QAction(i18n("Show &Line Numbers"), this);
0378     actionCollection()->addAction(QStringLiteral("line_numbers"), a);
0379     a->setStatusTip(i18n("Turn the line numbers on/off in the editor"));
0380     a->setWhatsThis(i18n("Show Line Numbers: Turn the line numbers on/off in the editor"));
0381     actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::Key_F11));
0382     a->setCheckable(true);
0383     a->setChecked(true);
0384     connect(a, &QAction::toggled, editor, &Editor::toggleLineNumbers);
0385 
0386     // Help menu actions
0387     contextHelpAct = ac->addAction(QStringLiteral("context_help"));
0388     contextHelpAct->setText(QLatin1String(""));
0389     contextHelpAct->setIcon(QIcon::fromTheme(QStringLiteral("help-about")));
0390     actionCollection()->setDefaultShortcut(contextHelpAct, QKeySequence(Qt::Key_F2));
0391     contextHelpAct->setStatusTip(i18n("Get help on the command under the cursor"));
0392     contextHelpAct->setWhatsThis(i18n("Context Help: Get help on the command under the cursor"));
0393     connect(contextHelpAct, &QAction::triggered, this, &MainWindow::contextHelp);
0394     updateContextHelpAction();
0395 
0396     a = actionCollection()->addAction(KStandardAction::HelpContents, QStringLiteral("help_contents"), this, SLOT(appHelpActivated()));
0397     a->setStatusTip(i18n("Help"));
0398     a->setWhatsThis(i18n("Help: Open manual for KTurtle"));
0399 
0400     // Menuless actions
0401     console = new Console(this);
0402     console->setText(i18n("Console"));
0403     actionCollection()->setDefaultShortcut(console, QKeySequence(Qt::Key_F4));
0404     actionCollection()->addAction(QStringLiteral("console"), console);
0405     connect(console, &Console::execute, this, &MainWindow::execute);
0406 
0407     executeConsoleAct = actionCollection()->addAction(QStringLiteral("execute_console"));
0408     executeConsoleAct->setIcon(QIcon::fromTheme(QStringLiteral("go-jump-locationbar")));
0409     executeConsoleAct->setText(i18n("Execute"));
0410     connect(executeConsoleAct, &QAction::triggered, console, &Console::executeActionTriggered);
0411     executeConsoleAct->setWhatsThis(i18n("Execute: Executes the current line in the console"));
0412 
0413     // The run speed action group
0414     QActionGroup* runSpeedGroup = new QActionGroup(this);
0415 
0416     // The run action collection, this is used in the toolbar to create a dropdown menu on the run button
0417     QAction* runSpeedAction = new QAction(QIcon::fromTheme(QStringLiteral("media-playback-start")), i18n("&Run"), this);
0418     connect(runSpeedAction, &QAction::triggered, this, &MainWindow::run);
0419     QMenu* runSpeedActionMenu = new QMenu(this);
0420     runSpeedAction->setMenu(runSpeedActionMenu);
0421     actionCollection()->addAction(QStringLiteral("run_speed"), runSpeedAction);
0422     runSpeedActionMenu->setStatusTip(i18n("Execute the program, or use the drop down menu to select the run speed"));
0423     runSpeedActionMenu->setWhatsThis(i18n("Run: Execute the program, or use the drop down menu to select the run speed"));
0424     connect(runSpeedActionMenu, &QMenu::triggered, this, &MainWindow::run);
0425 
0426     dedicatedSpeedAct = new QAction(i18nc("@option:radio", "Full Speed (&no highlighting and inspector)"), this);
0427     actionCollection()->addAction(QStringLiteral("dedicated_speed"), dedicatedSpeedAct);
0428     dedicatedSpeedAct->setCheckable(true);
0429     dedicatedSpeedAct->setStatusTip(i18n("Run the program at full speed, with highlighting and inspector disabled"));
0430     dedicatedSpeedAct->setWhatsThis(i18n("Full Speed: Run the program at full speed, with highlighting and inspector disabled"));
0431     connect(dedicatedSpeedAct, &QAction::triggered, this, &MainWindow::setDedicatedSpeed);
0432     runSpeedGroup->addAction(dedicatedSpeedAct);
0433     runSpeedActionMenu->addAction(dedicatedSpeedAct);
0434 
0435     fullSpeedAct = new QAction(i18nc("@option:radio", "&Full Speed"), this);
0436     actionCollection()->addAction(QStringLiteral("full_speed"), fullSpeedAct);
0437     fullSpeedAct->setCheckable(true);
0438     fullSpeedAct->setChecked(true);
0439     fullSpeedAct->setStatusTip(i18n("Run the program at full speed"));
0440     fullSpeedAct->setWhatsThis(i18n("Full Speed: Run the program at full speed"));
0441     connect(fullSpeedAct, &QAction::triggered, this, &MainWindow::setFullSpeed);
0442     runSpeedGroup->addAction(fullSpeedAct);
0443     runSpeedActionMenu->addAction(fullSpeedAct);
0444 
0445     slowSpeedAct = new QAction(i18nc("@option:radio choose the slow speed", "&Slow"), this);
0446     actionCollection()->addAction(QStringLiteral("slow_speed"), slowSpeedAct);
0447     slowSpeedAct->setCheckable(true);
0448     slowSpeedAct->setStatusTip(i18n("Run the program at a slow speed"));
0449     slowSpeedAct->setWhatsThis(i18n("Slow Speed: Run the program at a slow speed"));
0450     connect(slowSpeedAct, &QAction::triggered, this, &MainWindow::setSlowSpeed);
0451     runSpeedGroup->addAction(slowSpeedAct);
0452     runSpeedActionMenu->addAction(slowSpeedAct);
0453 
0454     slowerSpeedAct = new QAction(i18nc("@option:radio", "S&lower"), this);
0455     actionCollection()->addAction(QStringLiteral("slower_speed"), slowerSpeedAct);
0456     slowerSpeedAct->setCheckable(true);
0457     slowerSpeedAct->setStatusTip(i18n("Run the program at a slower speed"));
0458     slowerSpeedAct->setWhatsThis(i18n("Slower Speed: Run the program at a slower speed"));
0459     connect(slowerSpeedAct, &QAction::triggered, this, &MainWindow::setSlowerSpeed);
0460     runSpeedGroup->addAction(slowerSpeedAct);
0461     runSpeedActionMenu->addAction(slowerSpeedAct);
0462 
0463     slowestSpeedAct = new QAction(i18nc("@option:radio", "Sl&owest"), this);
0464     actionCollection()->addAction(QStringLiteral("slowest_speed"), slowestSpeedAct);
0465     slowestSpeedAct->setCheckable(true);
0466     slowestSpeedAct->setStatusTip(i18n("Run the program at the slowest speed"));
0467     slowestSpeedAct->setWhatsThis(i18n("Slowest Speed: Run the program at the slowest speed"));
0468     connect(slowestSpeedAct, &QAction::triggered, this, &MainWindow::setSlowestSpeed);
0469     runSpeedGroup->addAction(slowestSpeedAct);
0470     runSpeedActionMenu->addAction(slowestSpeedAct);
0471 
0472     stepSpeedAct = new QAction(i18nc("@option:radio", "S&tep-by-Step"), this);
0473     actionCollection()->addAction(QStringLiteral("step_speed"), stepSpeedAct);
0474     stepSpeedAct->setCheckable(true);
0475     stepSpeedAct->setStatusTip(i18n("Run the program one step at a time"));
0476     stepSpeedAct->setWhatsThis(i18n("Step Speed: Run the program one step at a time"));
0477     connect(stepSpeedAct, &QAction::triggered, this, &MainWindow::setStepSpeed);
0478     runSpeedGroup->addAction(stepSpeedAct);
0479     runSpeedActionMenu->addAction(stepSpeedAct);
0480 }
0481 
0482 
0483 void MainWindow::setupCanvas()
0484 {
0485     // put the canvas in a layout as the central widget of the mainwindow
0486     QWidget* centralWidget = new QWidget(this);
0487     QHBoxLayout* centralLayout = new QHBoxLayout(centralWidget);
0488     centralLayout->setContentsMargins(0, 0, 0, 0); 
0489     canvasTabWidget = new QTabWidget(this);
0490 
0491     canvasTab = new QWidget();
0492     QHBoxLayout* canvasLayout = new QHBoxLayout(canvasTab);
0493     canvas = new Canvas(this);
0494     canvas->setFocusPolicy(Qt::NoFocus);
0495     canvas->setRenderHint(QPainter::Antialiasing);
0496     canvas->setWhatsThis(i18n("Canvas: This is where the turtle moves and draws when the program is running"));
0497     canvasLayout->addWidget(canvas);
0498         canvasLayout->setContentsMargins(0, 0, 0, 0);
0499     canvasTabWidget->insertTab(0, canvasTab, i18n("&Canvas"));
0500 
0501     QWidget* errorTab = new QWidget();
0502     QHBoxLayout* errorLayout = new QHBoxLayout(errorTab);
0503     errorDialog = new ErrorDialog(this);
0504     errorLayout->addWidget(errorDialog);
0505     canvasTabWidget->insertTab(1, errorTab, i18n("E&rrors"));
0506 
0507     // a widget stach with 2 layers: 1st with only a canvas, 2nd with the canvas/error tabs 
0508     stackedWidget = new QStackedWidget;
0509     stackedWidget->insertWidget(0, canvasTab);
0510     stackedWidget->insertWidget(1, canvasTabWidget);
0511 
0512     centralLayout->addWidget(stackedWidget);
0513     setCentralWidget(centralWidget);
0514 }
0515 
0516 void MainWindow::showErrorDialog(bool show)
0517 {
0518     if (show) {
0519         // show the canvas and errors in a tab widget, focussing on the errors
0520         stackedWidget->setCurrentIndex(1);
0521         canvasTabWidget->insertTab(0, canvasTab, i18n("&Canvas"));
0522         canvasTabWidget->setCurrentIndex(1);
0523         actionCollection()->action(QStringLiteral("show_errors"))->setChecked(true);
0524     } else {
0525         // show the canvas only
0526         stackedWidget->insertWidget(0, canvasTab);
0527         stackedWidget->setCurrentIndex(0);
0528         actionCollection()->action(QStringLiteral("show_errors"))->setChecked(false);
0529     }
0530 }
0531 
0532 
0533 void MainWindow::setupDockWindows()
0534 {
0535     editorDock = new LocalDockWidget(i18n("&Editor"), this);
0536     editorDock->setObjectName(QStringLiteral("editor"));
0537     QWidget* editorWrapWidget = new QWidget(editorDock);
0538     QHBoxLayout* editorDockLayout = new QHBoxLayout(editorWrapWidget);
0539     editorDockLayout->setContentsMargins(MARGIN_SIZE, MARGIN_SIZE, MARGIN_SIZE, MARGIN_SIZE);
0540     editorWrapWidget->setLayout(editorDockLayout);
0541 //  dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
0542     editor = new Editor(editorWrapWidget);  // create this here to prevent crashes
0543     editorDockLayout->addWidget(editor);
0544     editorDock->setWidget(editorWrapWidget);
0545 //  editorDock->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable);
0546     addDockWidget(Qt::LeftDockWidgetArea, editorDock);
0547     editor->show();
0548     editor->setFocus();
0549     editor->setWhatsThis(i18n("Editor: Write your KTurtle commands here"));
0550 
0551     // Creating the debug window
0552     inspectorDock = new LocalDockWidget(i18n("&Inspector"), this);
0553     inspectorDock->setObjectName(QStringLiteral("inspector"));
0554     QWidget* inspectorWrapWidget = new QWidget(inspectorDock);
0555     QHBoxLayout* inspectorDockLayout = new QHBoxLayout(inspectorWrapWidget);
0556     inspectorDockLayout->setContentsMargins({});
0557     inspectorWrapWidget->setLayout(inspectorDockLayout);
0558     inspector = new Inspector(inspectorWrapWidget);
0559     inspectorDockLayout->addWidget(inspector);
0560     inspectorDock->setWidget(inspectorWrapWidget);
0561     addDockWidget(Qt::RightDockWidgetArea, inspectorDock);
0562     inspector->setWhatsThis(i18n("Inspector: See information about variables and functions when the program runs"));
0563 }
0564 
0565 void MainWindow::setupEditor()
0566 {
0567 //  editor->setTranslator(Translator::instance());
0568     connect(editor, &Editor::modificationChanged, this, &MainWindow::updateModificationState);
0569     connect(editor, &Editor::contentNameChanged, this, &MainWindow::updateContentName);
0570     connect(editor, &Editor::fileOpened, this, &MainWindow::addToRecentFilesList);
0571     connect(editor, &Editor::fileSaved, this, &MainWindow::addToRecentFilesList);
0572     connect(editor, &Editor::cursorPositionChanged, this, &MainWindow::updateOnCursorPositionChange);
0573 }
0574 
0575 void MainWindow::setupInterpreter()
0576 {
0577     interpreter = new Interpreter(this, false);
0578     connect(interpreter, &Interpreter::finished, this, &MainWindow::abort);
0579     Executer* executer = interpreter->getExecuter();
0580 
0581     // the code to connect the executer with the canvas is auto generated:
0582 #include "interpreter/gui_connect.inc"
0583     connect(interpreter, &Interpreter::treeUpdated, inspector, &Inspector::updateTree);
0584 
0585     toggleGuiFeedback(true);
0586 }
0587 
0588 void MainWindow::toggleGuiFeedback(bool b)
0589 {
0590     Executer* executer = interpreter->getExecuter();
0591     if (b) {
0592         connect(executer, &Executer::currentlyExecuting, editor, &Editor::markCurrentWord);
0593         connect(executer, &Executer::currentlyExecuting, inspector, &Inspector::markTreeNode);
0594             
0595         connect(executer, &Executer::variableTableUpdated, inspector, &Inspector::updateVariable);
0596         connect(executer, &Executer::functionTableUpdated, inspector, &Inspector::updateFunction);
0597     } else {
0598         disconnect(executer, &Executer::currentlyExecuting, editor, &Editor::markCurrentWord);
0599         disconnect(executer, &Executer::currentlyExecuting, inspector, &Inspector::markTreeNode);
0600         
0601         disconnect(executer, &Executer::variableTableUpdated,
0602             inspector, &Inspector::updateVariable);
0603         disconnect(executer, &Executer::functionTableUpdated,
0604             inspector, &Inspector::updateFunction);
0605         editor->removeMarkings();
0606     }
0607 }
0608 
0609 void MainWindow::setupStatusBar()
0610 {
0611     statusBarLanguageLabel = new QLabel(statusBar());
0612     statusBar()->addPermanentWidget(statusBarLanguageLabel, 0);
0613     statusBarLanguageLabel->setAlignment(Qt::AlignRight);
0614 
0615     statusBarPositionLabel = new QLabel(statusBar());
0616     statusBar()->addPermanentWidget(statusBarPositionLabel, 0);
0617     statusBarPositionLabel->setAlignment(Qt::AlignRight);
0618 
0619     statusBarOverwriteModeLabel = new QLabel(statusBar());
0620     statusBar()->addPermanentWidget(statusBarOverwriteModeLabel, 0);
0621     statusBarOverwriteModeLabel->setAlignment(Qt::AlignRight);
0622 
0623     statusBarFileNameLabel = new QLabel(statusBar());
0624     statusBar()->addPermanentWidget(statusBarFileNameLabel, 0);
0625     statusBarFileNameLabel->setAlignment(Qt::AlignRight);
0626 
0627     toggleOverwriteMode(false);
0628     updateOnCursorPositionChange();
0629 }
0630 
0631 void MainWindow::saveNewToolbarConfig()
0632 {
0633     // this destroys our actions lists ...
0634     KXmlGuiWindow::saveNewToolbarConfig();
0635     // ... so plug them again
0636     updateLanguagesMenu();
0637     updateExamplesMenu();
0638 }
0639 
0640 void MainWindow::updateLanguagesMenu()
0641 {
0642     QList<QAction *> languageList;
0643     QActionGroup* languageGroup = new QActionGroup(this);
0644     connect(languageGroup, &QActionGroup::triggered, this, &MainWindow::setLanguage);
0645     QAction* a;
0646     // sort the dictionaries using an algorithm found in the qt docs:
0647     QMap<QString, QString> map;
0648     const QSet<QString> dictionaries = KLocalizedString::availableApplicationTranslations();
0649     for (const QString &lang_code : dictionaries)
0650         map.insert(codeToFullName(lang_code), lang_code);
0651     // populate the menu:
0652     for (const QString &lang_code : std::as_const(map)) {
0653         a = new QAction(codeToFullName(lang_code), actionCollection());
0654         a->setData(lang_code);
0655         a->setStatusTip(i18n("Switch to the %1 dictionary", codeToFullName(lang_code)));
0656         a->setCheckable(true);
0657         if (lang_code == currentLanguageCode) {
0658             a->setChecked(true);
0659         }
0660         //languageMenu->addAction(a);
0661         languageGroup->addAction(a);
0662         languageList.append(a);
0663     }
0664     unplugActionList (QStringLiteral("languages_actionlist"));
0665     plugActionList   (QStringLiteral("languages_actionlist"), languageList);
0666 }
0667 
0668 void MainWindow::updateExamplesMenu()
0669 {
0670     QAction * newExample;
0671     QActionGroup* exampleGroup = new QActionGroup (this);
0672     QList<QAction*> exampleList;
0673     const auto exampleNames{Translator::instance()->exampleNames()};
0674     for (const QString &exampleName : exampleNames) {
0675         newExample = new QAction (exampleName, this);
0676         newExample->setData(exampleName);
0677         exampleGroup->addAction (newExample);
0678 
0679         connect(newExample, &QAction::triggered, this, &MainWindow::openExample);
0680         exampleList.append (newExample);
0681     }
0682 
0683     QStringList allExamples;
0684     const QStringList exampleDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String(GHNS_TARGET), QStandardPaths::LocateDirectory);
0685     for (const QString &dir : exampleDirs) {
0686         const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.turtle"), QDir::Files);
0687         for (const QString &fileName : fileNames) {
0688             allExamples.append(dir + QLatin1Char('/') + fileName);
0689         }
0690     }
0691 
0692     if(!allExamples.isEmpty()) {
0693         newExample = new QAction(this);
0694         newExample->setSeparator(true);
0695         exampleGroup->addAction(newExample);
0696         exampleList.append(newExample);
0697     }
0698 
0699     for (const QString& exampleFilename : std::as_const(allExamples)) {
0700         QFileInfo fileInfo(exampleFilename);
0701         newExample = new QAction (fileInfo.baseName(), this);
0702         newExample->setData(exampleFilename);
0703         exampleGroup->addAction (newExample);
0704         exampleList.append (newExample);
0705             
0706         connect(newExample, &QAction::triggered, this, &MainWindow::openDownloadedExample);
0707     }
0708 
0709     unplugActionList (QStringLiteral("examples_actionlist"));
0710     plugActionList   (QStringLiteral("examples_actionlist"), exampleList);
0711 }
0712 
0713 void MainWindow::addToRecentFilesList(const QUrl &url)
0714 {
0715     recentFilesAction->addUrl(url);
0716 }
0717 
0718 void MainWindow::openExample()
0719 {
0720     QAction* action = qobject_cast<QAction*>(sender());
0721     QString exampleName = action->data().toString();
0722     editor->openExample(Translator::instance()->example(exampleName), exampleName);
0723 }
0724 
0725 void MainWindow::openDownloadedExample()
0726 {
0727     QAction* action = qobject_cast<QAction*>(sender());
0728     QString exampleFilename = action->data().toString();
0729     editor->openFile(QUrl::fromLocalFile(exampleFilename));
0730 }
0731 
0732 void MainWindow::toggleOverwriteMode(bool b)
0733 {
0734     statusBarOverwriteModeLabel->setText(b ? i18n(" OVR ") : i18n(" INS "));
0735     editor->setOverwriteMode(b);
0736 }
0737 
0738 void MainWindow::updateContextHelpAction(const QString& s, const QString& anchor)
0739 {
0740     //qDebug() << QStringLiteral("'%1' help anchor '%2'.").arg(s, anchor);
0741     contextHelpAnchor = anchor;
0742     contextHelpString = s.isEmpty() ? i18n("<nothing under cursor>") : s;
0743     contextHelpAct->setText(i18n("Help on: %1", contextHelpString));
0744 }
0745 
0746 void MainWindow::updateOnCursorPositionChange()
0747 {
0748     statusBarPositionLabel->setText(i18n(" Line: %1 Column: %2 ", editor->row(), editor->col()));
0749 
0750     Token* cursorToken = editor->currentToken();
0751     if (cursorToken) {
0752         QString look = cursorToken->look();
0753         int cat = cursorToken->category();
0754         delete cursorToken;
0755         cursorToken = nullptr;
0756         KLocalizedString layout = ki18n("\"%1\" <%2>");
0757         switch (cat) {
0758             // not showing the look (only the name):
0759             case Token::VariableCategory:     updateContextHelpAction(i18n("<variable>"), QStringLiteral("assignment-of-variables")); return;
0760             case Token::NumberCategory:       updateContextHelpAction(i18n("<number>"), QStringLiteral("reference.html#number")); return;
0761             case Token::CommentCategory:      updateContextHelpAction(i18n("<comment>"), QStringLiteral("reference.html#comment")); return;
0762             case Token::StringCategory:       updateContextHelpAction(i18n("<string>"), QStringLiteral("reference.html#string")); return;
0763             // only showing the look:
0764             case Token::LearnCommandCategory: updateContextHelpAction(look, QStringLiteral("learn")); return;
0765             case Token::TrueFalseCategory:    updateContextHelpAction(look, QStringLiteral("reference.html#boolean-value")); return;
0766             // showing the look and the name:
0767             case Token::ScopeCategory:
0768                 updateContextHelpAction(layout.subs(look).subs(i18n("scope")).toString(), QStringLiteral("reference")); return;
0769             case Token::AssignmentCategory:
0770                 updateContextHelpAction(layout.subs(look).subs(i18n("assignment")).toString(), QStringLiteral("assignment-of-variables")); return;
0771             case Token::ParenthesisCategory:
0772                 updateContextHelpAction(layout.subs(look).subs(i18n("parenthesis")).toString(), QStringLiteral("operators.html#mathematical-operators")); return;
0773             case Token::MathOperatorCategory:
0774                 updateContextHelpAction(layout.subs(look).subs(i18n("mathematical operator")).toString(), QStringLiteral("operators.html#mathematical-operators")); return;
0775             case Token::ExpressionCategory:
0776                 updateContextHelpAction(layout.subs(look).subs(i18n("expression")).toString(), QStringLiteral("operators")); return;
0777             case Token::BooleanOperatorCategory:
0778                 updateContextHelpAction(layout.subs(look).subs(i18n("boolean operator")).toString(), QStringLiteral("operators.html#boolean-operators")); return;
0779             case Token::FunctionCallCategory:
0780                 updateContextHelpAction(layout.subs(look).subs(i18n("learned command")).toString(), QStringLiteral("learn")); return;
0781             case Token::ArgumentSeparatorCategory:
0782                 updateContextHelpAction(layout.subs(look).subs(i18n("argument separator")).toString(), QStringLiteral("reference")); return;
0783             // showing the look and the name, and linking to the help through their default look (en_US):
0784             case Token::CommandCategory:
0785                 updateContextHelpAction(layout.subs(look).subs(i18n("command")).toString(), QStringLiteral("commands"));
0786                 return;
0787             case Token::ControllerCommandCategory:
0788                 updateContextHelpAction(layout.subs(look).subs(i18n("controller command")).toString(), QStringLiteral("controlling-execution"));
0789                 return;
0790         }
0791     }
0792     updateContextHelpAction();  // display the 'nothing under cursor thing'
0793 }
0794 
0795 
0796 void MainWindow::setLanguage(QAction *action)
0797 {
0798     if (setCurrentLanguage(action->data().toString()))
0799         action->setChecked(true);
0800 }
0801 
0802 bool MainWindow::setCurrentLanguage(const QString &lang_code)  // 2 or 5 digit code (en, en_US, nl, pt_BR)
0803 {
0804     bool result = false;
0805     //qDebug() << "MainWindow::setCurrentLanguage: " << lang_code;
0806     if (Translator::instance()->setLanguage(lang_code)) {
0807         currentLanguageCode = lang_code;
0808         statusBarLanguageLabel->setText(QLatin1Char(' ') + codeToFullName(lang_code) + QLatin1Char(' '));
0809         updateExamplesMenu();
0810         editor->rehighlight();
0811         result = true;
0812     } else {
0813         KMessageBox::error(this, i18n("Could not change the language to %1.", codeToFullName(lang_code)));
0814     }
0815     return result;
0816 }
0817 
0818 QString MainWindow::codeToFullName(const QString& lang_code)
0819 {
0820     return QString(lang_code == QLatin1String("en_US") ?
0821             i18n("English [built in]") :
0822             i18n("%1 (%2)", QLocale(lang_code.left(2)).nativeLanguageName(), lang_code)
0823         );
0824 }
0825 
0826 
0827 void MainWindow::run()
0828 {
0829     if (interpreter->state() == Interpreter::Uninitialized ||
0830         interpreter->state() == Interpreter::Finished ||
0831         interpreter->state() == Interpreter::Aborted) {
0832         // reset inspector and interpreter
0833         editor->removeMarkings();
0834         inspector->clear();
0835         errorDialog->clear();
0836         showErrorDialog(false);
0837         interpreter->initialize(editor->content());
0838     }
0839     editor->disable();
0840     console->disable();
0841     executeConsoleAct->setEnabled(false);
0842     toggleGuiFeedback(runSpeed != 0);
0843 
0844     // start parsing (always in full speed)
0845     iterationTimer->setSingleShot(false);
0846     iterationTimer->start(0);
0847 }
0848 
0849 QString MainWindow::execute(const QString &operation)
0850 {
0851     disconnect(interpreter, &Interpreter::finished, this, &MainWindow::abort);
0852     disconnect(interpreter, &Interpreter::treeUpdated, inspector, &Inspector::updateTree);
0853     Executer* executer = interpreter->getExecuter();
0854     disconnect(executer, &Executer::currentlyExecuting, editor, &Editor::markCurrentWord);
0855     disconnect(executer, &Executer::currentlyExecuting, inspector, &Inspector::markTreeNode);
0856     disconnect(executer, &Executer::variableTableUpdated,
0857         inspector, &Inspector::updateVariable);
0858     disconnect(executer, &Executer::functionTableUpdated,
0859         inspector, &Inspector::updateFunction);
0860 
0861     if (interpreter->state() == Interpreter::Uninitialized ||
0862         interpreter->state() == Interpreter::Finished ||
0863         interpreter->state() == Interpreter::Aborted) {
0864         interpreter->initialize(operation);
0865     }
0866 
0867     runAct->setEnabled(false);
0868     pauseAct->setEnabled(false);
0869     abortAct->setEnabled(false);
0870 
0871     currentlyRunningConsole = true;
0872 
0873     while (!(interpreter->state() == Interpreter::Finished ||
0874              interpreter->state() == Interpreter::Aborted)) {
0875         interpreter->interpret();
0876     }
0877     
0878     currentlyRunningConsole = false;
0879 
0880     runAct->setEnabled(true);
0881     pauseAct->setEnabled(false);
0882     abortAct->setEnabled(false);
0883 
0884     QString errorMessage;
0885 
0886     if (interpreter->encounteredErrors()) {
0887         ErrorList* errorList = interpreter->getErrorList();
0888         //qDebug() << errorList->first().text();
0889         errorMessage = errorList->first().text();
0890     }
0891 
0892     connect(interpreter, &Interpreter::finished, this, &MainWindow::abort);
0893     connect(interpreter, &Interpreter::treeUpdated, inspector, &Inspector::updateTree);
0894     connect(executer, &Executer::currentlyExecuting, editor, &Editor::markCurrentWord);
0895     connect(executer, &Executer::currentlyExecuting, inspector, &Inspector::markTreeNode);
0896     connect(executer, &Executer::variableTableUpdated, inspector, &Inspector::updateVariable);
0897     connect(executer, &Executer::functionTableUpdated, inspector, &Inspector::updateFunction);
0898 
0899     return errorMessage;
0900 }
0901 
0902 void MainWindow::iterate()
0903 {
0904     if (interpreter->state() == Interpreter::Finished || interpreter->state() == Interpreter::Aborted) {
0905         abort();
0906         return;
0907     }
0908 
0909     runAct->setEnabled(false);
0910     pauseAct->setChecked(false);
0911     pauseAct->setEnabled(true);
0912     abortAct->setEnabled(true);
0913 
0914     if (interpreter->state() == Interpreter::Executing) {
0915         iterationTimer->stop();
0916         iterationTimer->setSingleShot(true);
0917         switch (runSpeed) {
0918             case 0: iterationTimer->start(0);    break;
0919             case 1: iterationTimer->start(0);    break;
0920             case 2: iterationTimer->start(500);  break;
0921             case 3: iterationTimer->start(1000); break;
0922             case 4: iterationTimer->start(3000); break;
0923             case 5:
0924                 iterationTimer->stop();
0925                 interpreter->interpret();
0926                 pauseAct->setChecked(true);
0927                 pause();
0928                 return;
0929         }
0930     }
0931     interpreter->interpret();
0932 }
0933 
0934 void MainWindow::pause()
0935 {
0936     if (pauseAct->isChecked()) {
0937         runAct->setEnabled(true);
0938         iterationTimer->stop();
0939         return;
0940     }
0941     iterate();
0942 }
0943 
0944 void MainWindow::abort()
0945 {
0946     iterationTimer->stop();
0947     interpreter->abort();
0948 
0949     editor->removeMarkings();
0950     inspector->clearAllMarks();
0951 
0952     runAct->setEnabled(true);
0953     pauseAct->setChecked(false);
0954     pauseAct->setEnabled(false);
0955     abortAct->setEnabled(false);
0956 
0957     editor->enable();
0958     console->enable();
0959     executeConsoleAct->setEnabled(true);
0960 
0961     if (interpreter->encounteredErrors()) {
0962         errorDialog->setErrorList(interpreter->getErrorList());
0963         showErrorDialog(true);
0964     }
0965 }
0966 
0967 
0968 void MainWindow::updateContentName(const QString& str)
0969 {
0970     QString caption = str.isEmpty() ? i18n("untitled") : str;
0971     bool modified = editor->isModified();
0972     setWindowTitle(caption + QLatin1String("[*]"));
0973     setWindowModified(modified);
0974     statusBarFileNameLabel->setText(QStringLiteral(" %1%2 ").arg(caption).arg(modified ? QStringLiteral("*") : QString()));
0975 }
0976 
0977 void MainWindow::addToRecentFiles(const QUrl &url)
0978 {
0979     recentFilesAction->addUrl(url);
0980 }
0981 
0982 
0983 void MainWindow::readConfig()
0984 {
0985     KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("General Options"));
0986 //  m_paShowStatusBar->setChecked(config->readEntry("ShowStatusBar", QVariant(false)).toBool());
0987 //  m_paShowPath->setChecked(config->readEntry("ShowPath", QVariant(false)).toBool());
0988     recentFilesAction->loadEntries(KSharedConfig::openConfig()->group(QStringLiteral("Recent Files")));
0989     QString lang_code(config.readEntry("currentLanguageCode", QVariant(QString())).toString());
0990     if (lang_code.isEmpty()) lang_code = QStringLiteral("en_US");  // null-string are saved as empty-strings
0991     setCurrentLanguage(lang_code);
0992 //  if(m_paShowStatusBar->isChecked())
0993 //      statusBar()->show();
0994 //  else
0995 //      statusBar()->hide();
0996 }
0997 
0998 void MainWindow::writeConfig()
0999 {
1000     KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("General Options"));
1001 //  config.writeEntry("ShowStatusBar",m_paShowStatusBar->isChecked());
1002 //  config.writeEntry("ShowPath",m_paShowPath->isChecked());
1003     recentFilesAction->saveEntries(KSharedConfig::openConfig()->group(QStringLiteral("Recent Files")));
1004     config.writeEntry("currentLanguageCode", currentLanguageCode);
1005     config.sync();
1006 }
1007 
1008 void MainWindow::exportToPng()
1009 {
1010     // copied from edit code for file selection
1011     QUrl url = QFileDialog::getSaveFileUrl(this,
1012                            i18n("Save as Picture"),
1013                            QUrl(),
1014                            QStringLiteral("%1 (*.png);;%2 (*)").arg(i18n("PNG Images")).arg(i18n("All files")));
1015     if (url.isEmpty())
1016         return;
1017     // get our image from the canvas and save to png
1018     QImage pict = canvas->getPicture();
1019     if (url.isLocalFile()) {
1020         pict.save(url.toLocalFile(), "PNG");
1021     } else {
1022         pict.save(url.path(), "PNG");
1023     }
1024 }
1025 
1026 void MainWindow::exportToSvg()
1027 {
1028     // copied from edit code for file selection
1029     // canvas->saveAsSvg() does not handle QUrl, so only local files are accepted
1030     QString path = QFileDialog::getSaveFileName(this, i18nc("@title:window", "Save as SVG"), QString(), QStringLiteral("%1 (.*svg);;%2 (*)").arg(i18n("Scalable Vector Graphics")).arg(i18n("All files")));
1031     if (path.isEmpty())
1032         return;
1033     canvas->saveAsSvg(windowTitle(), path);
1034 }
1035 
1036 void MainWindow::exportToHtml()
1037 {
1038     // copied from edit code for file selection
1039     // we do not handle QUrl, so only local files are accepted
1040     QString path = QFileDialog::getSaveFileName(this, i18nc("@title:window", "Save code as HTML"), QString(), QStringLiteral("%1 (*.html);;%2 (*)").arg(i18n("HTML documents")).arg(i18n("All files")));
1041     if (path.isEmpty())
1042         return;
1043     QSaveFile file(path);
1044     if (!file.open(QIODevice::WriteOnly))
1045         return;
1046     QTextStream out(&file);
1047     out << editor->toHtml(windowTitle(), currentLanguageCode);
1048     out.flush();
1049     file.commit();
1050 }
1051 
1052 
1053 // slots for logo functions that need to use the MainWindow class:
1054 
1055 void MainWindow::slotInputDialog(QString& value)
1056 {
1057     iterationTimer->stop();
1058     value = QInputDialog::getText(this, i18n("Input"), i18n("Input"), QLineEdit::Normal, value);
1059     
1060     if(!currentlyRunningConsole)
1061         run();
1062 }
1063 
1064 void MainWindow::slotMessageDialog(const QString& text)
1065 {
1066     iterationTimer->stop();
1067     KMessageBox::information(this, text, i18n("Message"));
1068     if(!currentlyRunningConsole)
1069         run();
1070 }
1071 
1072 #include "moc_mainwindow.cpp"