File indexing completed on 2022-09-27 12:31:12

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