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"