50 #include "ScriptingPlugin.hh"
54 #if QT_VERSION >= 0x050000
60 ScriptingPlugin::ScriptingPlugin() :
67 highlighterCurrent_(0),
73 #ifdef ENABLE_SCRIPT_DEBUGGER
74 #ifdef QT_SCRIPTTOOLS_LIB
84 if ( OpenFlipper::Options::nogui() )
92 emit getMenubarMenu(tr(
"&Scripting"), scriptingMenu,
true );
95 QAction* showWidget = scriptingMenu->addAction( tr(
"Show script editor") );
96 icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"scriptEditor.png");
97 showWidget->setIcon(icon);
98 connect( showWidget, SIGNAL( triggered() ) ,
99 this , SLOT( showScriptWidget() ));
104 QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
106 scriptWidget_->setWindowIcon( OpenFlipper::Options::OpenFlipperIcon() );
108 icon.addFile(iconPath+
"document-open.png");
109 scriptWidget_->actionLoad_Script->setIcon(icon);
111 icon.addFile(iconPath+
"document-save.png");
112 scriptWidget_->actionSave_Script->setIcon(icon);
114 icon.addFile(iconPath+
"document-save-as.png");
115 scriptWidget_->actionSave_Script_As->setIcon(icon);
117 icon.addFile(iconPath+
"window-close.png");
118 scriptWidget_->actionClose->setIcon(icon);
124 QToolBar* toolBar =
new QToolBar(tr(
"Scripting Toolbar"));
126 QAction* openButton =
new QAction(QIcon(iconPath +
"document-open.png"),
"Open", toolBar);
127 toolBar->addAction(openButton);
128 connect (openButton, SIGNAL( triggered() ),
this, SLOT( slotLoadScript() ) );
130 QAction* saveButton =
new QAction(QIcon(iconPath +
"document-save.png"),
"Save", toolBar);
131 toolBar->addAction(saveButton);
132 connect (saveButton, SIGNAL( triggered() ),
this, SLOT( slotSaveScript() ) );
134 QAction* saveAsButton =
new QAction(QIcon(iconPath +
"document-save-as.png"),
"Save as", toolBar);
135 toolBar->addAction(saveAsButton);
136 connect (saveAsButton, SIGNAL( triggered() ),
this, SLOT( slotSaveScriptAs() ) );
138 toolBar->addSeparator();
140 debuggerButton_ =
new QAction(QIcon(iconPath +
"script-debugger.png"),
"Enable Debugger", toolBar);
141 debuggerButton_->setCheckable(
true);
142 toolBar->addAction(debuggerButton_);
144 #ifdef ENABLE_SCRIPT_DEBUGGER
146 debuggerButton_->setChecked(
true);
148 debuggerButton_->setChecked(
false);
150 connect (debuggerButton_, SIGNAL( triggered() ),
this, SLOT( slotDebuggerButton() ) );
152 debuggerButton_->setEnabled(
false);
153 debuggerButton_->setToolTip(tr(
"QtScriptTools library not available. Debugger is not available!"));
156 toolBar->addSeparator();
158 QAction* executeButton =
new QAction(QIcon(iconPath +
"arrow-right.png"),
"Execute", toolBar);
159 toolBar->addAction(executeButton);
160 connect (executeButton, SIGNAL( triggered() ),
this, SLOT( slotExecuteScriptButton() ) );
162 scriptWidget_->addToolBar(toolBar);
168 statusBar_ =
new QStatusBar();
170 scriptWidget_->setStatusBar( statusBar_ );
174 scriptWidget_->hide();
176 scriptWidget_->resize(scriptWidget_->width() , std::min(QApplication::desktop()->screenGeometry().height() - 150 , 800) );
178 connect (scriptWidget_->actionLoad_Script, SIGNAL( triggered() ),
this, SLOT( slotLoadScript() ) );
179 scriptWidget_->actionLoad_Script->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_O) );
180 connect (scriptWidget_->actionSave_Script, SIGNAL( triggered() ),
this, SLOT( slotSaveScript() ) );
181 scriptWidget_->actionSave_Script->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_S) );
182 connect (scriptWidget_->actionSave_Script_As, SIGNAL( triggered() ),
this, SLOT( slotSaveScriptAs() ) );
183 connect (scriptWidget_->actionClose, SIGNAL( triggered() ), scriptWidget_, SLOT( close() ) );
185 connect (scriptWidget_->currentScript, SIGNAL( textChanged() ),
this, SLOT( slotScriptChanged() ) );
187 connect (scriptWidget_->functionList, SIGNAL( currentItemChanged (QListWidgetItem*, QListWidgetItem*) ),
188 this, SLOT( slotFunctionClicked(QListWidgetItem*) ));
189 connect (scriptWidget_->functionList, SIGNAL( itemDoubleClicked(QListWidgetItem*) ),
190 this, SLOT( slotFunctionDoubleClicked(QListWidgetItem*) ));
193 connect (scriptWidget_->filterButton, SIGNAL( clicked() ),
194 this, SLOT( slotApplyFilter() ));
195 connect (scriptWidget_->resetButton, SIGNAL( clicked() ),
196 scriptWidget_->functionList, SLOT( reset() ));
197 connect (scriptWidget_->resetButton, SIGNAL( clicked() ),
198 scriptWidget_->filterEdit, SLOT( clear() ));
199 connect (scriptWidget_->functionList, SIGNAL(getDescription(QString,QString&,QStringList&,QStringList&)),
200 this , SIGNAL(getDescription(QString,QString&,QStringList&,QStringList&)));
202 scriptWidget_->description->setVisible(
false );
204 highlighterCurrent_ =
new Highlighter( scriptWidget_->currentScript->document() );
205 highlighterLive_ =
new Highlighter( scriptWidget_->liveEdit );
213 errorTimer_ =
new QTimer();
214 errorTimer_->setSingleShot(
true);
215 connect(errorTimer_,SIGNAL(timeout()),
this,SLOT(slotHighlightError()));
221 #ifdef ENABLE_SCRIPT_DEBUGGER
222 #ifdef QT_SCRIPTTOOLS_LIB
223 QScriptEngine* engine;
224 emit getScriptingEngine( engine );
225 debugger_ =
new QScriptEngineDebugger;
228 debugger_->attachTo(engine);
233 void ScriptingPlugin::slotApplyFilter(){
234 scriptWidget_->functionList->filter( scriptWidget_->filterEdit->text() );
238 scriptWidget_->actionSave_Script->setEnabled(
true );
244 const QString script = scriptWidget_->currentScript->toPlainText();
245 QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax ( script );
247 switch (syntaxCheck.state() ) {
248 case QScriptSyntaxCheckResult::Error :
249 lastProblemLine_ = syntaxCheck.errorLineNumber();
250 lastError_ = syntaxCheck.errorMessage();
251 errorTimer_->start(500);
253 case QScriptSyntaxCheckResult::Valid :
261 scriptWidget_->currentScript->highLightErrorLine(lastProblemLine_);
262 statusBar_->showMessage(lastError_,5000);
266 if ( OpenFlipper::Options::nogui() )
269 scriptWidget_->show();
272 QStringList completeList;
273 emit getAvailableFunctions( completeList );
276 QStringList functions;
278 scriptWidget_->functionList->clear( );
281 for (
int i = 0 ; i < completeList.size() ; ++i) {
283 QString plugin = completeList[i].section(
'.',0,0);
287 if ( ! plugins.contains( plugin ) )
288 plugins.push_back( plugin );
292 QString
function = completeList[i].section(
'.',1,1);
293 function =
function.section(
'(',0,0);
294 if ( ! functions.contains(
function ) )
295 functions.push_back(
function );
299 scriptWidget_->functionList->addItem( completeList[i] );
301 scriptWidget_->functionList->addItem( completeList[i].right(completeList[i].size() - 2) );
306 scriptWidget_->functionList->sortItems ( );
308 highlighterCurrent_->pluginPatterns_ = plugins;
309 highlighterCurrent_->functionPatterns_ = functions;
310 highlighterCurrent_->update();
311 highlighterCurrent_->rehighlight();
313 highlighterLive_->pluginPatterns_ = plugins;
314 highlighterLive_->functionPatterns_ = functions;
315 highlighterLive_->update();
316 highlighterLive_->rehighlight();
319 scriptWidget_->raise();
324 if ( OpenFlipper::Options::nogui() )
327 scriptWidget_->hide();
330 void ScriptingPlugin::slotScriptInfo( QString _pluginName , QString _functionName ) {
332 if ( OpenFlipper::Options::scripting() || OpenFlipper::Options::nogui() )
335 scriptWidget_->liveEdit->append( _pluginName +
"." + _functionName );
337 QScrollBar* bar = scriptWidget_->liveEdit->verticalScrollBar();
338 bar->setValue(bar->maximum());
343 if ( OpenFlipper::Options::gui())
344 statusBar_->showMessage(tr(
"Executing Script"));
346 QScriptEngine* engine;
347 emit getScriptingEngine( engine );
350 OpenFlipper::Options::scripting(
true);
353 engine->globalObject().setProperty(
"ScriptPath",OpenFlipper::Options::currentScriptDirStr());
356 if (_script.contains(QRegExp(
"^include <")) ) {
359 QStringList script = _script.split(QRegExp(
"[\r\n]"),QString::SkipEmptyParts);
362 int include_index = script.indexOf(QRegExp(
"^include.*"));
364 while ( include_index != -1) {
366 QString include_statement = script[include_index];
369 include_statement.remove(QRegExp(
"^include") );
370 include_statement.remove(
"<" );
371 include_statement.remove(
">" );
372 include_statement = include_statement.trimmed();
375 include_statement.replace(
"ScriptPath",OpenFlipper::Options::currentScriptDirStr());
377 QFile includeFile(include_statement);
379 if (!includeFile.exists() ) {
380 emit log(
LOGERR,
"Script file include not found : " + include_statement +
" from " + script[include_index] );
384 if (!includeFile.open(QFile::ReadOnly | QFile::Text)) {
385 emit log(
LOGERR,
"Unable to open file : " + include_statement);
389 QTextStream in(&includeFile);
390 script[include_index] = in.readAll();
395 _script = script.join(
"\n");
398 include_index = script.indexOf(QRegExp(
"^include.*"));
405 engine->evaluate( _script );
409 if ( engine->hasUncaughtException() ) {
411 QScriptValue result = engine->uncaughtException();
412 QString exception = result.toString();
413 int lineNumber = engine->uncaughtExceptionLineNumber();
414 emit log(
LOGERR , tr(
"Script execution failed at line %1, with : %2 ").arg(lineNumber).arg(exception) );
416 if ( OpenFlipper::Options::gui()) {
417 statusBar_->showMessage(tr(
"Script execution failed at line %1, with : %2 ").arg(lineNumber).arg(exception));
420 QTextCursor cursor = scriptWidget_->currentScript->textCursor();
421 cursor.setPosition(0);
422 cursor.movePosition ( QTextCursor::Down, QTextCursor::MoveAnchor, lineNumber - 1 );
423 scriptWidget_->currentScript->setTextCursor(cursor);
425 scriptWidget_->currentScript->highLightErrorLine(lineNumber);
427 lastProblemLine_ = lineNumber;
428 lastError_ = exception;
433 if ( OpenFlipper::Options::gui() && !error)
434 statusBar_->clearMessage();
437 OpenFlipper::Options::scripting(
false);
440 void ScriptingPlugin::slotExecuteFileScript( QString _filename ) {
443 QFile data(_filename);
444 if (data.open(QFile::ReadOnly)) {
445 QTextStream input(&data);
447 script.append(input.readLine() +
"\n");
448 }
while (!input.atEnd());
450 if ( OpenFlipper::Options::gui() )
451 scriptWidget_->currentScript->setPlainText(script);
454 OpenFlipper::Options::currentScriptDir( _filename.section(OpenFlipper::Options::dirSeparator(), 0, -2) );
456 slotExecuteScript(script);
459 emit log(
LOGERR,tr(
"Unable to open script file!"));
462 void ScriptingPlugin::slotExecuteScriptButton() {
463 slotExecuteScript( scriptWidget_->currentScript->toPlainText() );
468 #ifdef ENABLE_SCRIPT_DEBUGGER
469 #ifdef QT_SCRIPTTOOLS_LIB
470 QScriptEngine* engine;
471 emit getScriptingEngine( engine );
473 if ( debuggerButton_->isChecked() ) {
474 debugger_->attachTo(engine);
485 QString ScriptingPlugin::mangleScript(QString _input ) {
488 QStringList functions;
489 emit getAvailableFunctions( functions );
491 std::cerr <<
"Todo : mangle script " << std::endl;
498 if ( OpenFlipper::Options::nogui() )
503 timer.setSingleShot(
true);
504 timer.start( _seconds * 1000 );
506 while (timer.isActive() )
507 QApplication::processEvents();
513 if ( OpenFlipper::Options::nogui() )
518 timer.setSingleShot(
true);
519 timer.start( _mseconds );
521 while (timer.isActive() )
522 QApplication::processEvents();
527 frameTime_.restart();
531 int elapsed = frameTime_.elapsed();
534 if ( elapsed < _mseconds ) {
535 sleepmsecs( _mseconds - elapsed );
539 frameTime_.restart();
545 if ( OpenFlipper::Options::nogui() )
550 box.addButton(tr(
"Continue"),QMessageBox::AcceptRole);
551 box.setText(tr(
"Script execution has been interrupted"));
552 box.setIcon(QMessageBox::Information);
553 box.setWindowModality(Qt::NonModal);
554 box.setWindowTitle(tr(
"Continue?"));
555 box.setWindowFlags( box.windowFlags() | Qt::WindowStaysOnTopHint);
558 while ( box.isVisible() )
559 QApplication::processEvents();
564 if ( OpenFlipper::Options::nogui() )
570 box.addButton(tr(
"Continue"),QMessageBox::AcceptRole);
572 box.setIcon(QMessageBox::Information);
573 box.setWindowModality(Qt::NonModal);
574 box.setWindowTitle(tr(
"Continue?"));
575 box.setWindowFlags( box.windowFlags() | Qt::WindowStaysOnTopHint);
580 while ( box.isVisible() )
581 QApplication::processEvents();
586 void ScriptingPlugin::slotLoadScript(){
588 QString lastOpened =
OpenFlipperSettings().
value(
"Scripting/CurrentDir",OpenFlipper::Options::currentScriptDirStr()).toString();
590 QString filename = QFileDialog::getOpenFileName(0,
591 tr(
"Load Script"),lastOpened , tr(
"Script Files (*.ofs)"));
596 QFileInfo info (filename);
599 slotLoadScript(filename);
602 void ScriptingPlugin::slotLoadScript( QString _filename ) {
608 if ( OpenFlipper::Options::gui() ) {
609 scriptWidget_->currentScript->clear();
611 QFile data(_filename);
613 if (data.open(QFile::ReadOnly)) {
614 QTextStream input(&data);
616 scriptWidget_->currentScript->appendPlainText(input.readLine());
617 }
while (!input.atEnd());
619 lastFile_ = _filename;
620 OpenFlipper::Options::currentScriptDir( QFileInfo(_filename).absolutePath() );
622 scriptWidget_->actionSave_Script->setEnabled(
false );
624 scriptWidget_->show();
630 void ScriptingPlugin::slotSaveScript(){
632 QFile file(lastFile_);
638 if (file.open(QFile::WriteOnly)) {
639 QTextStream output(&file);
640 output << scriptWidget_->currentScript->toPlainText();
642 scriptWidget_->actionSave_Script->setEnabled(
false );
646 void ScriptingPlugin::slotSaveScriptAs(){
647 QString lastOpened =
OpenFlipperSettings().
value(
"Scripting/CurrentDir",OpenFlipper::Options::currentScriptDirStr()).toString();
649 QString filename = QFileDialog::getSaveFileName(scriptWidget_,
650 tr(
"Save Script"),lastOpened, tr(
"Script Files (*.ofs)"));
652 if (filename ==
"")
return;
654 QFileInfo info (filename);
658 QFile data(filename);
662 QFileInfo fi(filename);
663 if (fi.completeSuffix() ==
""){
664 filename = filename +
".ofs";
665 data.setFileName(filename);
670 if (data.open(QFile::WriteOnly)) {
671 QTextStream output(&data);
672 output << scriptWidget_->currentScript->toPlainText();
675 lastFile_ = filename;
676 OpenFlipper::Options::currentScriptDir( QFileInfo(filename).absolutePath() );
678 scriptWidget_->actionSave_Script->setEnabled(
false );
681 void ScriptingPlugin::slotFunctionClicked(QListWidgetItem * _item)
687 QString slotDescription;
689 QStringList descriptions;
691 emit getDescription(_item->text(), slotDescription, params, descriptions);
693 if ( !slotDescription.isEmpty() ){
695 if (descriptionLabels_.count() > 0){
697 for (
int i = 0; i < descriptionLabels_.count(); i++){
698 descrLayout_->removeWidget( descriptionLabels_[i] );
699 delete descriptionLabels_[i];
701 descriptionLabels_.clear();
703 descrLayout_ =
new QVBoxLayout();
705 QLabel* lSlotName =
new QLabel(
"<B>" + _item->text() +
"</B>");
706 QLabel* lDescription =
new QLabel(slotDescription);
707 lDescription->setWordWrap(
true);
709 descrLayout_->addWidget(lSlotName);
710 descrLayout_->addWidget(lDescription);
712 descriptionLabels_.append(lSlotName);
713 descriptionLabels_.append(lDescription);
715 if ( params.count() == descriptions.count() ){
718 QString typeStr = _item->text().section(
"(",1,1).section(
")",0,0);
719 QStringList types = typeStr.split(
",");
721 if (types.count() == params.count()){
723 for(
int p=0; p < params.count(); p++ ){
724 QLabel* param =
new QLabel(
"<B>" + types[p] +
" " + params[p] +
":</B>" );
725 QLabel* descr =
new QLabel(descriptions[p]);
726 descr->setWordWrap(
true);
727 descrLayout_->addWidget(param);
728 descrLayout_->addWidget(descr);
730 descriptionLabels_.append(param);
731 descriptionLabels_.append(descr);
739 scriptWidget_->description->setLayout( descrLayout_ );
742 scriptWidget_->description->setVisible( !slotDescription.isEmpty() );
745 void ScriptingPlugin::slotFunctionDoubleClicked(QListWidgetItem * _item)
747 scriptWidget_->currentScript->insertPlainText( _item->text() );
752 if ( OpenFlipper::Options::nogui() )
760 OpenFlipper::Options::currentScriptDir(
"" );
764 scriptWidget_->currentScript->setPlainText(_code);
768 if ( OpenFlipper::Options::nogui() )
771 scriptWidget_->currentScript->clear();
774 #if QT_VERSION < 0x050000
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
void pluginsInitialized()
void frameStart()
Marks the current time as the frame start ( Use wait sleepFrameLength to wait until _mseconds have pa...
void slotDebuggerButton()
Triggered by the debugger button.
void sleep(int _seconds)
Sleeps for some seconds in script execution ( Gui will remain functional)
void clearEditor()
Clear the editor window Clears the script editor window.
void showScriptWidget()
Show the script editor widget.
void sleepmsecs(int _mseconds)
Sleeps for some mseconds in script execution ( Gui will remain functional)
void slotExecuteScript(QString _script)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
void slotScriptChanged()
Called everytime the text in the scriptingwidget is changed by the user.
void waitFrameEnd(int _mseconds)
wait until _mseconds have passed since frameStart (if more time has passed, it will return immediatel...
void slotHighlightError()
Called when an error is detected when checking the syntax.
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
void showScriptInEditor(QString _code)
Show the given Code in the script editor.
void hideScriptWidget()
Hide the script editor widget.