2 * KTurtle, Copyright (C) 2003-04 Cies Breijs <cies # kde ! nl>
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of version 2 of the GNU General Public
6 License as published by the Free Software Foundation.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 // BEGIN includes and defines
28 #include <qwhatsthis.h>
30 #include <kapplication.h>
31 #include <kconfigdialog.h>
33 #include <kedittoolbar.h>
34 #include <kfiledialog.h>
36 #include <kinputdialog.h>
38 #include <kmessagebox.h>
41 #include <ksavefile.h>
42 #include <kstatusbar.h>
44 #include <ktexteditor/clipboardinterface.h>
45 #include <ktexteditor/cursorinterface.h>
46 #include <ktexteditor/editorchooser.h>
47 #include <ktexteditor/editinterface.h>
48 #include <ktexteditor/highlightinginterface.h>
49 #include <ktexteditor/printinterface.h>
50 #include <ktexteditor/selectioninterface.h>
51 #include <ktexteditor/undointerface.h>
52 #include <ktexteditor/viewcursorinterface.h>
56 #include "translate.h"
60 // StatusBar field IDs
62 #define IDS_LINECOLUMN 2
70 // BEGIN constructor and destructor
72 MainWindow::MainWindow(KTextEditor::Document
*document
) : editor(0)
75 CurrentFile
= KURL(); // fill with empty URL
76 setCaption( i18n("Untitled") );
77 picker
= 0; // for the colorpickerdialog
81 // set the shell's ui resource file
84 if ( !(document
= KTextEditor::EditorChooser::createDocument(0,"KTextEditor::Document") ) )
86 KMessageBox::error( this, i18n("A KDE text-editor component could not be found;\n"
87 "please check your KDE installation.") );
90 // docList.append(doc);
100 setMinimumSize(200,200);
102 // init with more usefull size, stolen from kwite (they stole it from konq)
103 if ( !initialGeometrySet() && !kapp
->config()->hasGroup("MainWindow Settings") ) resize(640, 480);
105 KConfig
*config
= kapp
->config();
109 MainWindow::~MainWindow()
111 delete editor
->document();
118 // BEGIN setup's (actions, editor, statusbar, canvas)
120 void MainWindow::setupActions()
122 KActionCollection
*ac
= actionCollection(); // abbreviation
125 KStdAction::openNew(this, SLOT(slotNewFile()), ac
);
126 openExAction
= new KAction(i18n("Open Exa&mples..."), "bookmark_folder", CTRL
+Key_E
, this, SLOT(slotOpenExample()), ac
, "open_examples");
127 KStdAction::open(this, SLOT(slotOpenFile()), ac
);
128 m_recentFiles
= KStdAction::openRecent(this, SLOT(slotOpenFile(const KURL
&)), ac
);
129 KStdAction::save(this, SLOT(slotSaveFile()), ac
);
130 KStdAction::saveAs(this, SLOT(slotSaveAs()), ac
);
131 new KAction(i18n("Save &Canvas..."), 0, 0, this, SLOT(slotSaveCanvas()), ac
, "save_canvas");
132 speed
= new KSelectAction(i18n("Execution Speed"), 0, ALT
+Key_S
, this, SLOT( slotChangeSpeed() ), ac
, "speed");
133 QStringList speeds
; speeds
<< i18n("Full Speed") << i18n("Slow") << i18n("Slower") << i18n("Slowest");
134 speed
->setItems(speeds
);
135 speed
->setCurrentItem(0);
136 run
= new KAction(i18n("&Execute Commands"), "gear", ALT
+Key_Return
, this, SLOT( slotExecute() ), ac
, "run");
137 pause
= new KToggleAction(i18n("Pause E&xecution"), "player_pause", Key_Pause
, this, SLOT( slotPauseExecution() ), ac
, "pause");
138 pause
->setChecked(false);
139 pause
->setEnabled(false);
140 stop
= new KAction(i18n("Stop E&xecution"), "stop", Key_Escape
, this, SLOT( slotAbortExecution() ), ac
, "stop");
141 stop
->setEnabled(false);
142 KStdAction::print(this, SLOT(slotPrint()), ac
);
143 KStdAction::quit(this, SLOT(close()), ac
);
146 KStdAction::undo(this, SLOT(slotUndo()), ac
);
147 KStdAction::redo(this, SLOT(slotRedo()), ac
);
148 KStdAction::cut(this, SLOT(slotCut()), ac
);
149 KStdAction::copy(this, SLOT(slotCopy()), ac
);
150 KStdAction::paste(this, SLOT(slotPaste()), ac
);
151 KStdAction::selectAll(this, SLOT(slotSelectAll()), ac
);
152 KStdAction::deselect(this, SLOT(slotClearSelection()), ac
);
153 new KToggleAction(i18n("Toggle Insert"), Key_Insert
, this, SLOT(slotToggleInsert()), ac
, "set_insert");
154 KStdAction::find(this, SLOT(slotFind()), ac
);
155 KStdAction::findNext(this, SLOT(slotFindNext()), ac
);
156 KStdAction::findPrev(this, SLOT(slotFindPrevious()), ac
);
157 KStdAction::replace(this, SLOT(slotReplace()), ac
);
160 new KToggleAction(i18n("Show &Line Numbers"), 0, Key_F11
, this, SLOT(slotToggleLineNumbers()), ac
, "line_numbers");
161 m_fullscreen
= KStdAction::fullScreen(this, SLOT(slotToggleFullscreen()), ac
, this, "full_screen");
162 m_fullscreen
->setChecked(b_fullscreen
);
165 colorpicker
= new KToggleAction(i18n("&Color Picker"), "colorize", ALT
+Key_C
, this, SLOT(slotColorPicker()), ac
, "color_picker");
166 new KAction(i18n("&Indent"), "indent", CTRL
+Key_I
, this, SLOT(slotIndent()), ac
, "edit_indent");
167 new KAction(i18n("&Unindent"), "unindent", CTRL
+SHIFT
+Key_I
, this, SLOT(slotUnIndent()), ac
, "edit_unindent");
168 new KAction(i18n("Cl&ean Indentation"), 0, 0, this, SLOT(slotCleanIndent()), ac
, "edit_cleanIndent");
169 new KAction(i18n("Co&mment"), 0, CTRL
+Key_D
, this, SLOT(slotComment()), ac
, "edit_comment");
170 new KAction(i18n("Unc&omment"), 0, CTRL
+SHIFT
+Key_D
, this, SLOT(slotUnComment()), ac
, "edit_uncomment");
173 KStdAction::preferences( this, SLOT(slotSettings()), ac
);
174 new KAction(i18n("&Configure Editor..."), "configure", 0, this, SLOT(slotEditor()), ac
, "set_confdlg");
177 ContextHelp
= new KAction(0, 0, Key_F2
, this, SLOT(slotContextHelp()), ac
, "context_help");
178 slotContextHelpUpdate(); // this sets the label of this action
181 setXMLFile("kturtleui.rc");
185 void MainWindow::setupEditor()
187 editorDock
= new QDockWindow(this);
188 editorDock
->setNewLine(true);
189 editorDock
->setFixedExtentWidth(250);
190 editorDock
->setFixedExtentHeight(150);
191 editorDock
->setResizeEnabled(true);
192 editorDock
->setFrameShape(QFrame::ToolBarPanel
);
193 QWhatsThis::add( editorDock
, i18n( "This is the code editor, here you type the Logo commands to instruct the turtle. You can also open an existing Logo program with File->Open Examples... or File->Open." ) );
194 moveDockWindow(editorDock
, Qt::DockLeft
);
195 editor
= doc
->createView (editorDock
, 0L);
196 // editorInterface is the editor interface which allows us to access the text in the part
197 editorInterface
= dynamic_cast<KTextEditor::EditInterface
*>(doc
);
198 editorDock
->setWidget(editor
);
200 // default the highlightstyle to "logo" using the needed i18n
201 kdDebug(0)<<"The HighlightStyle for the Code Editor: "<<Settings::logoLanguage()<<endl
;
202 slotSetHighlightstyle( Settings::logoLanguage() );
204 // allow the cursor position to be indicated in the statusbar
205 connect( editor
, SIGNAL(cursorPositionChanged()), this, SLOT(slotCursorStatusBar()) );
206 // and update the context help menu item
207 connect( editor
, SIGNAL(cursorPositionChanged()), this, SLOT(slotContextHelpUpdate()) );
209 translate
= new Translate();
212 void MainWindow::setupStatusBar()
214 statusBar()->insertItem("", IDS_STATUS
, 1, false);
215 statusBar()->setItemAlignment(IDS_STATUS
, AlignLeft
);
216 statusBar()->insertItem("", IDS_LANG
, 0, true);
217 statusBar()->insertItem("", IDS_LINECOLUMN
, 0, true);
218 statusBar()->insertItem("", IDS_INS
, 0, true);
220 // fill the statusbar
221 slotStatusBar(i18n("Welcome to KTurtle..."), IDS_STATUS
); // the message part
222 slotStatusBar(i18n("Line: %1 Column: %2").arg(1).arg(1), IDS_LINECOLUMN
);
223 slotStatusBar(i18n("INS"), IDS_INS
);
226 void MainWindow::setupCanvas()
228 baseWidget
= new QWidget(this);
229 setCentralWidget(baseWidget
);
230 baseLayout
= new QGridLayout(baseWidget
, 0, 0);
231 canvasView
= new Canvas(baseWidget
);
232 baseLayout
->addWidget(canvasView
, 0, 0, AlignCenter
);
233 baseLayout
->setRowStretch(0, 1); // this apperntly fixes a pre-usefull scrollbars bug
234 baseLayout
->setColStretch(0, 1);
235 QWhatsThis::add( canvasView
, i18n("This is the canvas, here the turtle draws a picture.") );
237 connect( canvasView
, SIGNAL( CanvasResized() ), this, SLOT( slotUpdateCanvas() ) );
244 // BEGIN staturbar related functions
246 void MainWindow::slotStatusBar(QString text
, int id
)
248 text
= " " + text
+ " "; // help the layout
249 statusBar()->changeItem(text
, id
);
252 void MainWindow::slotCursorStatusBar()
256 dynamic_cast<KTextEditor::ViewCursorInterface
*>(editor
)->cursorPositionReal(&cursorLine
, &cursorCol
);
257 QString linenumber
= i18n(" Line: %1 Column: %2 ").arg(cursorLine
+ 1).arg(cursorCol
+ 1);
258 statusBar()->changeItem(linenumber
, IDS_LINECOLUMN
);
265 // BEGIN file menu related fuctions (new, open, save()as, image, print, quit)
267 void MainWindow::slotNewFile()
269 if ( !editor
->document()->isModified() && CurrentFile
.isEmpty() ) return; // do nothing when nothing can be done
270 if ( editor
->document()->isModified() )
272 int result
= KMessageBox::warningContinueCancel( this,
273 i18n("The program you are currently working on is not saved. "
274 "By continuing you may lose the changes you have made."),
275 i18n("Unsaved File"), i18n("&Discard Changes") );
276 if (result
!= KMessageBox::Continue
) return;
278 editorInterface
->clear(); // clear the editor
279 canvasView
->slotClear(); // clear the view
280 editor
->document()->setModified(false);
281 CurrentFile
= KURL();
282 setCaption( i18n("Untitled") );
283 slotStatusBar(i18n("New file... Happy coding!"), IDS_STATUS
);
288 void MainWindow::slotOpenFile(const KURL
&urlRef
)
293 url
= KFileDialog::getOpenURL( QString(":logo_dir"), QString("*.logo|") + i18n("Logo Files"), this, i18n("Open Logo File") );
298 void MainWindow::slotOpenExample()
301 url
.setPath( locate("data", "kturtle/examples/" + Settings::logoLanguage() + "/") );
302 url
= KFileDialog::getOpenURL( url
.path(), QString("*.logo|") + i18n("Logo Examples Files"), this, i18n("Open Logo Example File") );
306 void MainWindow::loadFile(const KURL
&url
)
308 if ( !url
.isEmpty() )
310 QFile
file( url
.path() );
311 if ( file
.open(IO_ReadOnly
) )
313 if ( editor
->document()->isModified() )
315 int result
= KMessageBox::warningContinueCancel( this,
316 i18n("The program you are currently working on is not saved. "
317 "By continuing you may lose the changes you have made."),
318 i18n("Unsaved File"), i18n("&Discard Changes") );
319 if (result
!= KMessageBox::Continue
)
321 slotStatusBar(i18n("Opening aborted, nothing opened."), IDS_STATUS
);
325 QTextStream
stream(&file
);
326 stream
.setEncoding(QTextStream::UnicodeUTF8
);
327 editorInterface
->setText( stream
.read() );
329 m_recentFiles
->addURL(url
);
330 setCaption( url
.fileName() );
331 slotStatusBar(i18n("Opened file: %1").arg( url
.fileName() ), IDS_STATUS
);
332 editor
->document()->setModified(false);
338 KMessageBox::error( this,
339 i18n("KTurtle was unable to open: \n%1.").arg( url
.prettyURL() ),
340 i18n("Open Error") );
341 slotStatusBar(i18n("Opening aborted because of error."), IDS_STATUS
);
345 slotStatusBar(i18n("Opening aborted."), IDS_STATUS
); // fallback
348 void MainWindow::slotSaveFile()
350 writeFile(CurrentFile
);
353 void MainWindow::slotSaveAs()
358 url
= KFileDialog::getSaveURL( QString(":logo_dir"), QString("*.logo|") + i18n("Logo Files"), this, i18n("Save As") );
359 if ( url
.isEmpty() ) // cancelled the save dialog
361 slotStatusBar(i18n("Saving aborted."), IDS_STATUS
);
364 if ( QFile( url
.path() ).exists() )
366 int result
= KMessageBox::warningContinueCancel ( this,
367 i18n("A program named \"%1\" already exists in this folder. "
368 "Do you want to overwrite it?").arg( url
.fileName() ),
369 i18n("Overwrite?"), i18n("&Overwrite") );
370 if (result
!= KMessageBox::Continue
) return;
377 void MainWindow::writeFile(const KURL
&url
)
379 if ( url
.isEmpty() ) slotSaveAs();
382 QString mString
= editorInterface
->text(); // get the text
383 editorInterface
->setText( mString
.utf8() ); // convert it to utf8
384 editor
->document()->saveAs(url
); // use the KateParts method for saving
385 loadFile(url
); // reload the file as utf8 otherwise display weird chars
386 setCaption( url
.fileName() );
387 slotStatusBar(i18n("Saved to: %1").arg( url
.fileName() ), IDS_STATUS
);
388 m_recentFiles
->addURL(url
);
389 editor
->document()->setModified(false);
396 void MainWindow::slotSaveCanvas()
401 url
= KFileDialog::getSaveURL( QString(":logo_dir"), QString("*.png|") +
402 i18n("Pictures"), this, i18n("Save Canvas as Picture") );
403 if ( url
.isEmpty() ) return; // when cancelled the KFiledialog?
404 if ( QFile( url
.path() ).exists() )
406 int result
= KMessageBox::warningContinueCancel( this,
407 i18n("A picture named \"%1\" already in this folder. "
408 "Do you want to overwrite it?").arg( url
.fileName() ),
409 i18n("Overwrite?"), i18n("&Overwrite") );
410 if (result
!= KMessageBox::Continue
) return;
415 QString
type( KImageIO::type( url
.path() ) );
416 if ( type
.isNull() ) type
= "PNG";
418 QPixmap
* pixmap
= canvasView
->canvas2Pixmap();
419 if ( url
.isLocalFile() )
421 KSaveFile
saveFile( url
.path() );
422 if ( saveFile
.status() == 0 )
424 if ( pixmap
->save( saveFile
.file(), type
.latin1() ) ) ok
= saveFile
.close();
429 kdWarning() << "KTurtle was unable to save the canvas drawing" << endl
;
430 KMessageBox::error(this,
431 i18n("KTurtle was unable to save the image to: \n%1.").arg( url
.prettyURL() ),
432 i18n("Unable to Save Image") );
433 slotStatusBar(i18n("Could not save image."), IDS_STATUS
);
436 slotStatusBar(i18n("Saved canvas to: %1").arg( url
.fileName() ), IDS_STATUS
);
441 void MainWindow::slotPrint()
443 int result
= KMessageBox::questionYesNoCancel( this,
444 i18n("Do you want to print the Logo code or the canvas?"),
445 i18n("What to Print?"), i18n("Print &Logo Code"), i18n("Print &Canvas") );
446 if (result
== KMessageBox::Yes
)
448 dynamic_cast<KTextEditor::PrintInterface
*>(doc
)->printDialog();
451 if (result
== KMessageBox::No
)
454 if ( printer
.setup(this) )
456 QPainter
painter(&printer
);
457 QPixmap
*CanvasPic
= canvasView
->canvas2Pixmap();
458 painter
.drawPixmap(0, 0, *CanvasPic
);
462 slotStatusBar(i18n("Printing aborted."), IDS_STATUS
);
467 bool MainWindow::queryClose()
469 if ( editor
->document()->isModified() )
471 slotStatusBar(i18n("Quitting KTurtle..."), IDS_STATUS
);
472 // make sure the dialog looks good with new -- unnamed -- files.
473 int result
= KMessageBox::warningYesNoCancel( this,
474 i18n("The program you are currently working on is not saved. "
475 "By quitting KTurtle you may lose the changes you have made."),
476 i18n("Unsaved File"), i18n("&Save"), i18n("Discard Changes && &Quit") );
477 if (result
== KMessageBox::Cancel
)
479 slotStatusBar(i18n("Quitting aborted."), IDS_STATUS
);
482 else if (result
== KMessageBox::Yes
)
485 if ( CurrentFile
.isEmpty() )
487 // when saveAs get cancelled or X-ed it should not quit
488 slotStatusBar(i18n("Quitting aborted."), IDS_STATUS
);
493 KConfig
*config
= kapp
->config();
494 config
->setGroup("General Options");
495 m_recentFiles
->saveEntries(config
, "Recent Files");
504 // BEGIN run related functions
506 void MainWindow::slotExecute()
508 if (b_fullscreen
) // check if execution should be execution in 'fullscreen' mode
516 run
->setEnabled(false); // set action indications
517 pause
->setEnabled(true);
518 stop
->setEnabled(true);
521 slotStatusBar(i18n("Parsing commands..."), IDS_STATUS
);
522 kdDebug(0)<<"############## PARSING STARTED ##############"<<endl
;
523 kapp
->processEvents();
524 errMsg
= new ErrorMessage(this); // create an empty errorDialog
525 QString txt
= editorInterface
->text() + "\x0a\x0a"; // parser expects input to have 2 delimiting newlines
526 QTextIStream
in(&txt
); // create the stream
527 Parser
parser(in
); // pass the reference to the stream to the parse object
528 connect(&parser
, SIGNAL( ErrorMsg(Token
&, const QString
&, uint
) ),
529 errMsg
, SLOT( slotAddError(Token
&, const QString
&, uint
) ) );
530 connect( errMsg
, SIGNAL(setSelection(uint
, uint
, uint
, uint
) ),
531 this, SLOT(slotSetSelection(uint
, uint
, uint
, uint
) ) );
532 parser
.parse(); // and GO!
533 TreeNode
* root
= parser
.getTree(); // when finished parsing get the nodeTree
534 kdDebug(0)<<"############## PARSING FINISHED ##############"<<endl
;
536 kdDebug(0)<<"TreeNode::showTree():"<<endl
;
537 root
->showTree(root
); // show nodeTree, this is a DEBUG OPTION (but nice)
540 slotStatusBar(i18n("Executing commands..."), IDS_STATUS
);
541 kdDebug(0)<<"############## EXECUTION STARTED ##############"<<endl
;
542 exe
= new Executer(root
); // make Executer object, 'exe', and pass it the nodeTree
544 connect(this, SIGNAL( changeSpeed(int) ), exe
, SLOT(slotChangeSpeed(int) ) );
545 connect(this, SIGNAL( unpauseExecution() ), exe
, SLOT( slotStopPausing() ) );
546 connect( exe
, SIGNAL( setSelection(uint
, uint
, uint
, uint
) ),
547 this, SLOT ( slotSetSelection(uint
, uint
, uint
, uint
) ) );
548 connect( exe
, SIGNAL( ErrorMsg(Token
&, const QString
&, uint
) ),
549 errMsg
, SLOT ( slotAddError(Token
&, const QString
&, uint
) ) );
550 connect( exe
, SIGNAL( InputDialog(QString
&) ), this, SLOT( slotInputDialog(QString
&) ) );
551 connect( exe
, SIGNAL( MessageDialog(QString
) ), this, SLOT( slotMessageDialog(QString
) ) );
553 // Connect the signals form Executer to the slots from Canvas:
554 connect( exe
, SIGNAL( Clear() ), canvasView
, SLOT( slotClear() ) );
555 connect( exe
, SIGNAL( Go(double, double) ), canvasView
, SLOT( slotGo(double, double) ) );
556 connect( exe
, SIGNAL( GoX(double) ), canvasView
, SLOT( slotGoX(double) ) );
557 connect( exe
, SIGNAL( GoY(double) ), canvasView
, SLOT( slotGoY(double) ) );
558 connect( exe
, SIGNAL( Forward(double) ), canvasView
, SLOT( slotForward(double) ) );
559 connect( exe
, SIGNAL( Backward(double) ), canvasView
, SLOT( slotBackward(double) ) );
560 connect( exe
, SIGNAL( Direction(double) ), canvasView
, SLOT( slotDirection(double) ) );
561 connect( exe
, SIGNAL( TurnLeft(double) ), canvasView
, SLOT( slotTurnLeft(double) ) );
562 connect( exe
, SIGNAL( TurnRight(double) ), canvasView
, SLOT( slotTurnRight(double) ) );
563 connect( exe
, SIGNAL( Center() ), canvasView
, SLOT( slotCenter() ) );
564 connect( exe
, SIGNAL( SetPenWidth(int) ), canvasView
, SLOT( slotSetPenWidth(int) ) );
565 connect( exe
, SIGNAL( PenUp() ), canvasView
, SLOT( slotPenUp() ) );
566 connect( exe
, SIGNAL( PenDown() ), canvasView
, SLOT( slotPenDown() ) );
567 connect( exe
, SIGNAL( SetFgColor(int, int, int) ), canvasView
, SLOT( slotSetFgColor(int, int, int) ) );
568 connect( exe
, SIGNAL( SetBgColor(int, int, int) ), canvasView
, SLOT( slotSetBgColor(int, int, int) ) );
569 connect( exe
, SIGNAL( ResizeCanvas(int, int) ), canvasView
, SLOT( slotResizeCanvas(int, int) ) );
570 connect( exe
, SIGNAL( SpriteShow() ), canvasView
, SLOT( slotSpriteShow() ) );
571 connect( exe
, SIGNAL( SpriteHide() ), canvasView
, SLOT( slotSpriteHide() ) );
572 connect( exe
, SIGNAL( SpritePress() ), canvasView
, SLOT( slotSpritePress() ) );
573 connect( exe
, SIGNAL( SpriteChange(int) ), canvasView
, SLOT( slotSpriteChange(int) ) );
574 connect( exe
, SIGNAL( Print(QString
) ), canvasView
, SLOT( slotPrint(QString
) ) );
575 connect( exe
, SIGNAL( FontType(QString
, QString
) ), canvasView
, SLOT( slotFontType(QString
, QString
) ) );
576 connect( exe
, SIGNAL( FontSize(int) ), canvasView
, SLOT( slotFontSize(int) ) );
577 connect( exe
, SIGNAL( WrapOn() ), canvasView
, SLOT( slotWrapOn() ) );
578 connect( exe
, SIGNAL( WrapOff() ), canvasView
, SLOT( slotWrapOff() ) );
579 connect( exe
, SIGNAL( Reset() ), canvasView
, SLOT( slotReset() ) );
581 // START EXECUTION on the selected speed, and use the feedbacked boolean value
583 if ( exe
->run() ) slotStatusBar(i18n("Done."), IDS_STATUS
);
584 else slotStatusBar(i18n("Execution aborted."), IDS_STATUS
);
587 delete exe
; // clean-up
589 if ( errMsg
->containsErrors() ) errMsg
->display(); // if errors show them
592 void MainWindow::slotPauseExecution()
594 if ( pause
->isChecked() )
597 slotStatusBar(i18n("Execution paused."), IDS_STATUS
);
601 emit
unpauseExecution();
602 slotStatusBar(i18n("Executing commands..."), IDS_STATUS
);
606 void MainWindow::slotAbortExecution()
608 // To abort the executor, this can for instance be handy when the
609 // executer got stuck in a user made endless loops...
610 // to keep the program responding to interrupts like this, all the
611 // loops have possible breaks. This activates them breaks:
615 void MainWindow::finishExecution()
617 kdDebug(0)<<"############## EXECUTION FINISHED ##############"<<endl
;
619 pause
->setEnabled(false);
620 pause
->setChecked(false);
621 run
->setEnabled(true);
622 stop
->setEnabled(false);
624 // if execution finished on FullSpeed the selection does not match the last executed command -> clear-it
625 if (speed
->currentItem() == 0) slotClearSelection();
627 // if coming from fullscreen-mode show the editor, menu- and statusbar
628 if (b_fullscreen
) QTimer::singleShot( 1000, this, SLOT( slotFinishedFullScreenExecution() ) );
631 void MainWindow::slotChangeSpeed()
633 emit
changeSpeed( speed
->currentItem() );
637 // slots for logo functions that need to use the MainWindow class:
639 void MainWindow::slotInputDialog(QString
& value
)
641 value
= KInputDialog::getText(i18n("Input"), value
);
644 void MainWindow::slotMessageDialog(QString text
)
646 KMessageBox::information( this, text
, i18n("Message") );
653 // BEGIN editor connections (undo, redo, cut, copy, paste, cursor, selections, find, replace, linenumbers etc.)
655 void MainWindow::slotEditor()
657 KAction
*a
= editor
->actionCollection()->action("set_confdlg");
661 void MainWindow::slotSetHighlightstyle(QString langCode
)
663 KTextEditor::HighlightingInterface
*hli
= dynamic_cast<KTextEditor::HighlightingInterface
*>(doc
);
664 for (uint i
= 0; i
< hli
->hlModeCount(); i
++)
666 if (hli
->hlModeName(i
) == langCode
)
673 for (uint i
= 0; i
< hli
->hlModeCount(); i
++)
675 if(hli
->hlModeName(i
) == "en_US") hli
->setHlMode(i
);
680 void MainWindow::slotUndo()
682 dynamic_cast<KTextEditor::UndoInterface
*>(doc
)->undo();
685 void MainWindow::slotRedo()
687 dynamic_cast<KTextEditor::UndoInterface
*>(doc
)->redo();
691 void MainWindow::slotCut()
693 dynamic_cast<KTextEditor::ClipboardInterface
*>(editor
)->cut();
696 void MainWindow::slotCopy()
698 dynamic_cast<KTextEditor::ClipboardInterface
*>(editor
)->copy();
701 void MainWindow::slotPaste()
703 dynamic_cast<KTextEditor::ClipboardInterface
*>(editor
)->paste();
707 void MainWindow::slotSelectAll()
709 dynamic_cast<KTextEditor::SelectionInterface
*>(doc
)->selectAll();
712 void MainWindow::slotClearSelection()
714 dynamic_cast<KTextEditor::SelectionInterface
*>(doc
)->clearSelection();
717 void MainWindow::slotFind()
719 KAction
*a
= editor
->actionCollection()->action("edit_find");
723 void MainWindow::slotFindNext()
725 KAction
*a
= editor
->actionCollection()->action("edit_find_next");
729 void MainWindow::slotFindPrevious()
731 KAction
*a
= editor
->actionCollection()->action("edit_find_prev");
735 void MainWindow::slotReplace()
737 KAction
* a
= editor
->actionCollection()->action("edit_replace");
741 void MainWindow::slotToggleInsert()
743 KToggleAction
*a
= dynamic_cast<KToggleAction
*>(editor
->actionCollection()->action("set_insert"));
745 if (a
) statusBar()->changeItem(a
->isChecked() ? i18n(" OVR ") : i18n(" INS "), IDS_INS
);
748 void MainWindow::slotIndent()
750 KAction
*a
= editor
->actionCollection()->action("tools_indent");
754 void MainWindow::slotUnIndent()
756 KAction
*a
= editor
->actionCollection()->action("tools_unindent");
760 void MainWindow::slotCleanIndent()
762 KAction
*a
= editor
->actionCollection()->action("tools_cleanIndent");
766 void MainWindow::slotComment()
768 KAction
*a
= editor
->actionCollection()->action("tools_comment");
772 void MainWindow::slotUnComment()
774 KAction
*a
= editor
->actionCollection()->action("tools_uncomment");
778 void MainWindow::slotToggleLineNumbers()
780 KToggleAction
*a
= dynamic_cast<KToggleAction
*>( editor
->actionCollection()->action("view_line_numbers") );
784 void MainWindow::slotInsertText(QString str
)
786 uint StartLine
, StartCol
, EndLine
, EndCol
;
787 dynamic_cast<KTextEditor::ViewCursorInterface
*>(editor
)->cursorPositionReal(&StartLine
, &StartCol
);
788 dynamic_cast<KTextEditor::EditInterface
*>(doc
)->insertText(StartLine
, StartCol
, str
);
789 dynamic_cast<KTextEditor::ViewCursorInterface
*>(editor
)->cursorPositionReal(&EndLine
, &EndCol
);
790 dynamic_cast<KTextEditor::SelectionInterface
*>(doc
)->setSelection(StartLine
, StartCol
, EndLine
, EndCol
);
793 void MainWindow::slotSetCursorPos(uint row
, uint col
)
795 dynamic_cast<KTextEditor::ViewCursorInterface
*>(editor
)->setCursorPositionReal(row
- 1, col
);
796 // kdDebug(0)<<"Cursor set to: ("<<row-1<<", "<<col<<")"<<endl;
799 void MainWindow::slotSetSelection(uint StartLine
, uint StartCol
, uint EndLine
, uint EndCol
)
801 dynamic_cast<KTextEditor::SelectionInterface
*>(doc
)->setSelection(StartLine
- 1, StartCol
- 1, EndLine
- 1, EndCol
- 1);
802 // kdDebug(0)<<"Selection set to: ("<<StartLine<<", "<<StartCol<<", "<<EndLine<<", "<<EndCol<<")"<<endl;
808 // BEGIN fullscreen functions
810 void MainWindow::slotToggleFullscreen()
812 if (!b_fullscreen
) showFullScreen(); // both calls will generate event triggering updateFullScreen()
813 else if ( isFullScreen() ) showNormal();
816 bool MainWindow::event(QEvent
* e
)
818 // executes updateFullScreen() after a ShowFullScreen or ShowNormal event got triggered
819 if (e
->type() == QEvent::ShowFullScreen
|| e
->type() == QEvent::ShowNormal
) updateFullScreen();
820 return KMainWindow::event(e
);
823 void MainWindow::updateFullScreen()
825 if (isFullScreen() == b_fullscreen
) return;
826 b_fullscreen
= isFullScreen();
827 if (m_fullscreen
) m_fullscreen
->setChecked(b_fullscreen
);
830 void MainWindow::slotFinishedFullScreenExecution()
832 restartOrBackDialog
= new RestartOrBack(this); // we have to make some to delete some
833 if ( errMsg
->containsErrors() ) slotBackToFullScreen(); // straight back to edit if there where errors
836 connect( restartOrBackDialog
, SIGNAL( user1Clicked() ), this, SLOT( slotRestartFullScreen() ) );
837 connect( restartOrBackDialog
, SIGNAL( user2Clicked() ), this, SLOT( slotBackToFullScreen() ) );
838 connect( restartOrBackDialog
, SIGNAL( finished() ), this, SLOT( slotBackToFullScreen() ) );
839 restartOrBackDialog
->show();
840 restartOrBackDialog
->move(50, 50);
844 void MainWindow::slotBackToFullScreen()
846 delete restartOrBackDialog
;
853 void MainWindow::slotRestartFullScreen()
855 delete restartOrBackDialog
;
863 // BEGIN configuration related functions
865 void MainWindow::slotSettings()
867 // Check if there is already a dialog, if so bring it to the foreground.
868 if ( KConfigDialog::showDialog("settings") ) return;
870 // Create a new dialog with the same name as the above checking code.
871 KConfigDialog
*dialog
= new KConfigDialog(this, "settings", Settings::self() );
873 connect( dialog
, SIGNAL( helpClicked() ), this, SLOT( slotSettingsHelp() ) );
875 // making the filling for the 'General' settings dept.
876 general
= new QWidget();
877 QGridLayout
*generalLayout
= new QGridLayout( general
, 1, 1, 11, 6, "generalLayout");
878 WidthHeightBox
= new QGroupBox( i18n("Initial Canvas Size"), general
);
879 WidthHeightBox
->setColumnLayout(0, Qt::Vertical
);
880 WidthHeightBox
->layout()->setSpacing( 6 );
881 WidthHeightBox
->layout()->setMargin( 11 );
882 QVBoxLayout
*WidthHeightBoxLayout
= new QVBoxLayout( WidthHeightBox
->layout() );
883 WidthHeightBoxLayout
->setAlignment( Qt::AlignTop
);
884 QHBoxLayout
*layout3
= new QHBoxLayout( 0, 0, 6, "layout3");
885 QVBoxLayout
*layout2
= new QVBoxLayout( 0, 0, 6, "layout2");
887 QVBoxLayout
*layout1
= new QVBoxLayout( 0, 0, 6, "layout1");
889 kcfg_CanvasWidth
= new KIntNumInput( WidthHeightBox
, "kcfg_CanvasWidth" );
890 kcfg_CanvasWidth
->setValue( 400 );
891 kcfg_CanvasWidth
->setMinValue( 1 );
892 kcfg_CanvasWidth
->setReferencePoint( 1 );
893 layout1
->addWidget( kcfg_CanvasWidth
);
895 kcfg_CanvasHeight
= new KIntNumInput( WidthHeightBox
, "kcfg_CanvasHeight" );
896 kcfg_CanvasHeight
->setValue( 300 );
897 kcfg_CanvasHeight
->setMinValue( 1 );
898 kcfg_CanvasHeight
->setReferencePoint( 1 );
899 layout1
->addWidget( kcfg_CanvasHeight
);
901 WidthLabel
= new QLabel( kcfg_CanvasWidth
, i18n("Canvas &width:"), WidthHeightBox
);
902 layout2
->addWidget( WidthLabel
);
903 HeightLabel
= new QLabel( kcfg_CanvasHeight
, i18n("Ca&nvas height:"), WidthHeightBox
);
904 layout2
->addWidget( HeightLabel
);
905 layout3
->addLayout( layout2
);
907 layout3
->addLayout( layout1
);
908 WidthHeightBoxLayout
->addLayout( layout3
);
909 QLabel
* WidthHeightLabel
= new QLabel(i18n("You need to restart before these settings have effect"), WidthHeightBox
);
910 WidthHeightBoxLayout
->addWidget( WidthHeightLabel
);
911 generalLayout
->addWidget( WidthHeightBox
, 0, 0 );
912 general
->resize( QSize(234, 109).expandedTo(minimumSizeHint()) );
914 dialog
->addPage( general
, i18n("General"), "package_settings", i18n("General Settings") );
916 // making the filling for the 'Language' settings dept.
917 QWidget
*language
= new QWidget();
918 QGridLayout
*languageLayout
= new QGridLayout( language
, 1, 1, 11, 6, "Form1Layout");
919 QGroupBox
*groupBox1
= new QGroupBox( language
, "groupBox1" );
920 groupBox1
->setColumnLayout(0, Qt::Vertical
);
921 groupBox1
->layout()->setSpacing( 6 );
922 groupBox1
->layout()->setMargin( 11 );
923 QGridLayout
*groupBox1Layout
= new QGridLayout( groupBox1
->layout() );
924 groupBox1Layout
->setAlignment( Qt::AlignTop
);
926 QVBoxLayout
*layout4
= new QVBoxLayout( 0, 0, 6, "layout4");
928 kcfg_LanguageComboBox
= new KComboBox(groupBox1
, "kcfg_LanguageComboBox");
929 kcfg_LanguageComboBox
->setEditable(false);
930 QStringList LogoLanguageList
= Settings::logoLanguageList();
931 // Add the full language names to the items
932 for ( QStringList::Iterator it
= LogoLanguageList
.begin(); it
!= LogoLanguageList
.end(); ++it
) {
933 *it
= KGlobal::locale()->twoAlphaToLanguageName( (*it
).left(2) ) + " (" + *it
+ ")";
935 kcfg_LanguageComboBox
->insertStringList(LogoLanguageList
);
937 LanguageLabel
= new QLabel(kcfg_LanguageComboBox
, i18n("&Select the language for the Logo commands:"), groupBox1
);
938 layout4
->addWidget( LanguageLabel
);
939 layout4
->addWidget( kcfg_LanguageComboBox
);
940 LanguageLabel
->setBuddy( kcfg_LanguageComboBox
);
942 groupBox1Layout
->addLayout( layout4
, 0, 0 );
943 languageLayout
->addWidget( groupBox1
, 0, 0 );
944 language
->resize( QSize(373, 80).expandedTo(minimumSizeHint()) );
946 dialog
->addPage( language
, i18n("Language"), "locale", i18n("Language Settings") );
948 // When the user clicks OK or Apply we want to update our settings.
949 connect( dialog
, SIGNAL( settingsChanged() ), this, SLOT( slotUpdateSettings() ) );
951 // Display the dialog is there where errors.
952 dialog
->setInitialSize( QSize(550, 300) );
956 void MainWindow::slotUpdateSettings()
958 // get the selected language as a language code
959 QString selectedLogoLanguage
= kcfg_LanguageComboBox
->currentText().section( "(", -1, -1 ).remove(")");
960 // update the settings
961 Settings::setLogoLanguage( selectedLogoLanguage
);
962 Settings::setLanguageComboBox( kcfg_LanguageComboBox
->currentItem() );
963 Settings::writeConfig();
965 slotSetHighlightstyle( selectedLogoLanguage
);
966 // set the statusbar to display the language as just updated
967 // TODO maybe this language name can be more pretty by not using ".left(2)", ie "American English" would than be possible... [if this is possible this should be fixed at more places.]
968 KConfig
entry(locate("locale", "all_languages"));
969 entry
.setGroup(Settings::logoLanguage().left(2));
970 slotStatusBar(i18n("Command language: %1").arg( entry
.readEntry("Name") ), IDS_LANG
);
972 delete translate
; // to update the currently used language
973 translate
= new Translate();
976 void MainWindow::readConfig(KConfig
*config
)
978 config
->setGroup("General Options");
979 m_recentFiles
->loadEntries(config
, "Recent Files");
980 KConfig
entry(locate("locale", "all_languages"));
981 entry
.setGroup(Settings::logoLanguage().left(2));
982 slotStatusBar(i18n("Command language: %1").arg( entry
.readEntry("Name") ), IDS_LANG
);
985 void MainWindow::slotSettingsHelp()
987 kapp
->invokeHelp("settings-configure", "", "");
994 // BEGIN help related functions
996 void MainWindow::slotContextHelp()
998 // somehow the 'anchor' parameter of invokeHelp is not working correcctly (yet)
1000 // this is/was appearently a bug in KHTML that Waldo Bastian kindly and quikly fixed.
1002 // Ooh... and we also want a DCOPmethod to close the sidebar since it over-informs...
1003 // Ooh3... we want fancy help (using KHTML) @ errormessage dialog
1004 // Ooh4... And we might also have to keep track of the KHelpCenter instance we open so
1005 // we will not end up with loads of them
1008 // IDEA!!: put all the keyword in a i18n("...") this will make translating them a lot easier!!!
1009 // MAYBE THIS IS ALSO POSSIBLE FOR THE INTERPRETER!!!!
1010 // this should be discussed with translators (and please think of the highlight-themes too (since
1011 // right now thay can probably be translated with a simple perl script
1013 kdDebug(0)<<"help requested on this text: "<<helpKeyword
<<endl
;
1016 if ( helpKeyword
== i18n("<no keyword>") )
1018 KMessageBox::information( this, i18n("There is currently no text under the cursor to get help on."), i18n("Nothing Under Cursor") );
1021 else if ( helpKeyword
== i18n("<number>") ) helpWord
= "number";
1022 else if ( helpKeyword
== i18n("<string>") ) helpWord
= "string";
1023 else if ( helpKeyword
== i18n("<assignment>") ) helpWord
= "assignment";
1024 else if ( helpKeyword
== i18n("<question>") ) helpWord
= "questions";
1025 else if ( helpKeyword
== i18n("<name>") ) helpWord
= "name";
1026 else if ( helpKeyword
== i18n("<comment>") ) helpWord
= "comment";
1030 helpWord
= helpKeyword
.lower();
1031 // if the key is an alias translate that alias to a key
1032 if ( !translate
->alias2key(helpKeyword
).isEmpty() ) helpWord
= translate
->alias2key(helpKeyword
);
1033 else if ( !translate
->name2key (helpKeyword
).isEmpty() ) helpWord
= translate
->name2key (helpKeyword
);
1035 // at this point helpKeyword should contain a valid
1036 // section/anchor-id that can be used found in the doc
1037 // if not... who cares :)... well let's put an debugMsg for that occasion:
1038 else kdDebug(0)<<"Error in MainWindow::slotContextHelp: could not translate \""<<helpKeyword
<<"\""<<endl
;
1041 kdDebug(0)<<"trying to open a help page using this keyword: "<<helpWord
<<endl
;
1043 kapp
->invokeHelp(helpWord
, "", "");
1045 QString help2statusBar
;
1046 if ( helpKeyword
.startsWith("<") ) help2statusBar
= helpKeyword
;
1047 else help2statusBar
= i18n("\"%1\"").arg(helpKeyword
);
1048 slotStatusBar(i18n("Displaying help on %1").arg(help2statusBar
), IDS_STATUS
);
1051 void MainWindow::slotContextHelpUpdate()
1054 dynamic_cast<KTextEditor::ViewCursorInterface
*>(editor
)->cursorPositionReal(&row
, &col
);
1055 QString line
= dynamic_cast<KTextEditor::EditInterface
*>(doc
)->textLine(row
);
1057 // two shortcuts so we dont do all the CPU intensive regexp stuff when it not needed
1058 if ( line
.stripWhiteSpace().startsWith("#") )
1060 helpKeyword
= i18n("<comment>");
1061 ContextHelp
->setText( i18n("Help on: %1").arg(helpKeyword
) );
1064 if ( line
.stripWhiteSpace().isEmpty() || line
.mid(col
-1,2).stripWhiteSpace().isEmpty() )
1066 helpKeyword
= i18n("<no keyword>");
1067 ContextHelp
->setText( i18n("Help on: %1").arg(helpKeyword
) );
1071 int start
, length
, pos
;
1074 if ( line
.contains('"') )
1076 QRegExp
delimitedStrings("(\"[^\"\\\\\\r\\n]*(\\\\.[^\"\\\\\\r\\n]*)*\")");
1077 while ( delimitedStrings
.search(line
, pos
) != -1 )
1079 // kdDebug(0)<<"stringsearch: >>"<<pos<<"<<"<<endl;
1080 start
= delimitedStrings
.search(line
, pos
);
1081 length
= delimitedStrings
.matchedLength(); // the length of the last matched string, or -1 if there was no match
1082 if ( col
>= (uint
)start
&& col
< (uint
)(start
+length
) )
1084 helpKeyword
= i18n("<string>");
1085 ContextHelp
->setText( i18n("Help on: %1").arg(helpKeyword
) );
1088 pos
+= (length
<= 0 ? 1 : length
);
1093 // except for "strings" this regexp effectively separates logo code in 'words' (in a very broad meaning)
1094 QRegExp
splitter("(([^ ,+\\-*/()=<>[!]|(?!==|<=|>=|!=))*)|(([ ,+\\-*/()=<>[!]|==|<=|>=|!=))");
1097 while (splitter
.search(line
, pos
) != -1)
1099 start
= splitter
.search(line
, pos
);
1100 length
= splitter
.matchedLength();
1101 if ( col
< (uint
)start
) break;
1102 if ( col
>= (uint
)start
&& col
< (uint
)(start
+length
) )
1104 QString cursorWord
= line
.mid( (uint
)start
, (uint
)length
);
1105 // kdDebug(0)<<"splitsearch: >>"<<cursorWord<<"<<"<<endl;
1107 if ( cursorWord
.stripWhiteSpace().isEmpty() ) helpKeyword
= i18n("<no keyword>");
1109 else if ( !translate
->name2key( cursorWord
.lower() ).isEmpty() ||
1110 !translate
->alias2key( cursorWord
.lower() ).isEmpty() ) helpKeyword
= cursorWord
;
1112 else if ( cursorWord
.find( QRegExp("[\\d.]+") ) == 0 ) helpKeyword
= i18n("<number>");
1114 else if ( cursorWord
.find( QRegExp("[+\\-*/\\(\\)]") ) == 0 ) helpKeyword
= i18n("<math>");
1116 else if ( cursorWord
== QString("=") ) helpKeyword
= i18n("<assignment>");
1118 else if ( cursorWord
.find( QRegExp("==|<|>|<=|>=|!=") ) == 0 ) helpKeyword
= i18n("<question>");
1120 // if we come here we either have an ID of some sort or an error
1121 // all we can do is try to catch some errors (TODO) and then...
1123 else helpKeyword
= i18n("<name>");
1125 ContextHelp
->setText( i18n("Help on: %1").arg(helpKeyword
) );
1128 pos
+= (length
<= 0 ? 1 : length
); // the pos had to be increased with at least one
1131 // we allready cached some in the beginning of this method; yet its still needed as fall-through
1132 helpKeyword
= i18n("<no keyword>");
1133 ContextHelp
->setText( i18n("Help on: %1").arg(helpKeyword
) );
1140 // BEGIN misc. functions
1142 void MainWindow::slotColorPicker()
1144 // in the constructor picker is initialised as 0
1145 // if picker is 0 when this funktion is called a colorpickerdialog is created and connected
1148 picker
= new ColorPicker(this);
1149 if(picker
== 0) return; // safety
1150 connect( picker
, SIGNAL( visible(bool) ), colorpicker
, SLOT( setChecked(bool) ) );
1151 connect( picker
, SIGNAL( ColorCode(QString
) ), this, SLOT( slotInsertText(QString
) ) );
1153 // if picker is not 0, there is a colorpickerdialog which only needs to be shown OR hidden
1154 if ( picker
->isHidden() )
1157 colorpicker
->setChecked(true);
1162 colorpicker
->setChecked(false);
1166 void MainWindow::slotUpdateCanvas()
1168 // fixes a non updateing bug
1169 // I tried doing this by connecting Canvas's resized to baseWidget's update...
1170 // but i had no luck :( ... this worked though :)
1178 #include "kturtle.moc"