44 #include "ScriptingPlugin.hh" 50 ScriptingPlugin::ScriptingPlugin() :
57 highlighterCurrent_(0),
63 #ifdef ENABLE_SCRIPT_DEBUGGER
64 #ifdef QT_SCRIPTTOOLS_LIB
74 if ( OpenFlipper::Options::nogui() )
82 emit getMenubarMenu(tr(
"&Scripting"), scriptingMenu,
true );
85 QAction* showWidget = scriptingMenu->addAction( tr(
"Show script editor") );
86 icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"scriptEditor.png");
87 showWidget->setIcon(icon);
88 connect( showWidget, SIGNAL( triggered() ) ,
89 this , SLOT( showScriptWidget() ));
94 QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();
96 scriptWidget_->setWindowIcon( OpenFlipper::Options::OpenFlipperIcon() );
98 icon.addFile(iconPath+
"document-open.png");
99 scriptWidget_->actionLoad_Script->setIcon(icon);
101 icon.addFile(iconPath+
"document-save.png");
102 scriptWidget_->actionSave_Script->setIcon(icon);
104 icon.addFile(iconPath+
"document-save-as.png");
105 scriptWidget_->actionSave_Script_As->setIcon(icon);
107 icon.addFile(iconPath+
"window-close.png");
108 scriptWidget_->actionClose->setIcon(icon);
114 QToolBar* toolBar =
new QToolBar(tr(
"Scripting Toolbar"));
116 QAction* openButton =
new QAction(QIcon(iconPath +
"document-open.png"),
"Open", toolBar);
117 toolBar->addAction(openButton);
118 connect (openButton, SIGNAL( triggered() ),
this, SLOT( slotLoadScript() ) );
120 QAction* saveButton =
new QAction(QIcon(iconPath +
"document-save.png"),
"Save", toolBar);
121 toolBar->addAction(saveButton);
122 connect (saveButton, SIGNAL( triggered() ),
this, SLOT( slotSaveScript() ) );
124 QAction* saveAsButton =
new QAction(QIcon(iconPath +
"document-save-as.png"),
"Save as", toolBar);
125 toolBar->addAction(saveAsButton);
126 connect (saveAsButton, SIGNAL( triggered() ),
this, SLOT( slotSaveScriptAs() ) );
128 toolBar->addSeparator();
130 debuggerButton_ =
new QAction(QIcon(iconPath +
"script-debugger.png"),
"Enable Debugger", toolBar);
131 debuggerButton_->setCheckable(
true);
132 toolBar->addAction(debuggerButton_);
134 #ifdef ENABLE_SCRIPT_DEBUGGER 136 debuggerButton_->setChecked(
true);
138 debuggerButton_->setChecked(
false);
140 connect (debuggerButton_, SIGNAL( triggered() ),
this, SLOT( slotDebuggerButton() ) );
142 debuggerButton_->setEnabled(
false);
143 debuggerButton_->setToolTip(tr(
"QtScriptTools library not available. Debugger is not available!"));
146 toolBar->addSeparator();
148 QAction* executeButton =
new QAction(QIcon(iconPath +
"arrow-right.png"),
"Execute", toolBar);
149 toolBar->addAction(executeButton);
150 connect (executeButton, SIGNAL( triggered() ),
this, SLOT( slotExecuteScriptButton() ) );
152 scriptWidget_->addToolBar(toolBar);
158 statusBar_ =
new QStatusBar();
160 scriptWidget_->setStatusBar( statusBar_ );
164 scriptWidget_->hide();
166 scriptWidget_->resize(scriptWidget_->width() , std::min(QApplication::desktop()->screenGeometry().height() - 150 , 800) );
168 connect (scriptWidget_->actionLoad_Script, SIGNAL( triggered() ),
this, SLOT( slotLoadScript() ) );
169 scriptWidget_->actionLoad_Script->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_O) );
170 connect (scriptWidget_->actionSave_Script, SIGNAL( triggered() ),
this, SLOT( slotSaveScript() ) );
171 scriptWidget_->actionSave_Script->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_S) );
172 connect (scriptWidget_->actionSave_Script_As, SIGNAL( triggered() ),
this, SLOT( slotSaveScriptAs() ) );
173 connect (scriptWidget_->actionClose, SIGNAL( triggered() ), scriptWidget_, SLOT( close() ) );
175 connect (scriptWidget_->currentScript, SIGNAL( textChanged() ),
this, SLOT( slotScriptChanged() ) );
177 connect (scriptWidget_->functionList, SIGNAL( currentItemChanged (QListWidgetItem*, QListWidgetItem*) ),
178 this, SLOT( slotFunctionClicked(QListWidgetItem*) ));
179 connect (scriptWidget_->functionList, SIGNAL( itemDoubleClicked(QListWidgetItem*) ),
180 this, SLOT( slotFunctionDoubleClicked(QListWidgetItem*) ));
183 connect (scriptWidget_->filterButton, SIGNAL( clicked() ),
184 this, SLOT( slotApplyFilter() ));
185 connect (scriptWidget_->resetButton, SIGNAL( clicked() ),
186 scriptWidget_->functionList, SLOT( reset() ));
187 connect (scriptWidget_->resetButton, SIGNAL( clicked() ),
188 scriptWidget_->filterEdit, SLOT( clear() ));
189 connect (scriptWidget_->functionList, SIGNAL(getDescription(QString,QString&,QStringList&,QStringList&)),
190 this , SIGNAL(getDescription(QString,QString&,QStringList&,QStringList&)));
192 scriptWidget_->description->setVisible(
false );
194 highlighterCurrent_ =
new Highlighter( scriptWidget_->currentScript->document() );
195 highlighterLive_ =
new Highlighter( scriptWidget_->liveEdit );
203 errorTimer_ =
new QTimer();
204 errorTimer_->setSingleShot(
true);
205 connect(errorTimer_,SIGNAL(timeout()),
this,SLOT(slotHighlightError()));
211 #ifdef ENABLE_SCRIPT_DEBUGGER 212 #ifdef QT_SCRIPTTOOLS_LIB 213 QScriptEngine* engine;
214 emit getScriptingEngine( engine );
215 debugger_ =
new QScriptEngineDebugger;
218 debugger_->attachTo(engine);
223 void ScriptingPlugin::slotApplyFilter(){
224 scriptWidget_->functionList->filter( scriptWidget_->filterEdit->text() );
228 scriptWidget_->actionSave_Script->setEnabled(
true );
234 const QString script = scriptWidget_->currentScript->toPlainText();
235 QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax ( script );
237 switch (syntaxCheck.state() ) {
238 case QScriptSyntaxCheckResult::Error :
239 lastProblemLine_ = syntaxCheck.errorLineNumber();
240 lastError_ = syntaxCheck.errorMessage();
241 errorTimer_->start(500);
243 case QScriptSyntaxCheckResult::Valid :
251 scriptWidget_->currentScript->highLightErrorLine(lastProblemLine_);
252 statusBar_->showMessage(lastError_,5000);
256 if ( OpenFlipper::Options::nogui() )
259 scriptWidget_->show();
262 QStringList completeList;
263 emit getAvailableFunctions( completeList );
266 QStringList functions;
268 scriptWidget_->functionList->clear( );
271 for (
int i = 0 ; i < completeList.size() ; ++i) {
273 QString plugin = completeList[i].section(
'.',0,0);
277 if ( ! plugins.contains( plugin ) )
278 plugins.push_back( plugin );
282 QString
function = completeList[i].section(
'.',1,1);
283 function =
function.section(
'(',0,0);
284 if ( ! functions.contains(
function ) )
285 functions.push_back(
function );
289 scriptWidget_->functionList->addItem( completeList[i] );
291 scriptWidget_->functionList->addItem( completeList[i].right(completeList[i].size() - 2) );
296 scriptWidget_->functionList->sortItems ( );
298 highlighterCurrent_->pluginPatterns_ = plugins;
299 highlighterCurrent_->functionPatterns_ = functions;
300 highlighterCurrent_->update();
301 highlighterCurrent_->rehighlight();
303 highlighterLive_->pluginPatterns_ = plugins;
304 highlighterLive_->functionPatterns_ = functions;
305 highlighterLive_->update();
306 highlighterLive_->rehighlight();
309 scriptWidget_->raise();
314 if ( OpenFlipper::Options::nogui() )
317 scriptWidget_->hide();
320 void ScriptingPlugin::slotScriptInfo( QString _pluginName , QString _functionName ) {
322 if ( OpenFlipper::Options::scripting() || OpenFlipper::Options::nogui() )
325 scriptWidget_->liveEdit->append( _pluginName +
"." + _functionName );
327 QScrollBar* bar = scriptWidget_->liveEdit->verticalScrollBar();
328 bar->setValue(bar->maximum());
333 if ( OpenFlipper::Options::gui())
334 statusBar_->showMessage(tr(
"Executing Script"));
336 QScriptEngine* engine;
337 emit getScriptingEngine( engine );
340 OpenFlipper::Options::scripting(
true);
343 engine->globalObject().setProperty(
"ScriptPath",OpenFlipper::Options::currentScriptDirStr());
346 if (_script.contains(QRegExp(
"^include <")) ) {
349 QStringList script = _script.split(QRegExp(
"[\r\n]"),QString::SkipEmptyParts);
352 int include_index = script.indexOf(QRegExp(
"^include.*"));
354 while ( include_index != -1) {
356 QString include_statement = script[include_index];
359 include_statement.remove(QRegExp(
"^include") );
360 include_statement.remove(
"<" );
361 include_statement.remove(
">" );
362 include_statement = include_statement.trimmed();
365 include_statement.replace(
"ScriptPath",OpenFlipper::Options::currentScriptDirStr());
367 QFile includeFile(include_statement);
369 if (!includeFile.exists() ) {
370 emit log(
LOGERR,
"Script file include not found : " + include_statement +
" from " + script[include_index] );
374 if (!includeFile.open(QFile::ReadOnly | QFile::Text)) {
375 emit log(
LOGERR,
"Unable to open file : " + include_statement);
379 QTextStream in(&includeFile);
380 script[include_index] = in.readAll();
385 _script = script.join(
"\n");
388 include_index = script.indexOf(QRegExp(
"^include.*"));
395 engine->evaluate( _script );
399 if ( engine->hasUncaughtException() ) {
401 QScriptValue result = engine->uncaughtException();
402 QString exception = result.toString();
403 int lineNumber = engine->uncaughtExceptionLineNumber();
404 emit log(
LOGERR , tr(
"Script execution failed at line %1, with : %2 ").arg(lineNumber).arg(exception) );
406 if ( OpenFlipper::Options::gui()) {
407 statusBar_->showMessage(tr(
"Script execution failed at line %1, with : %2 ").arg(lineNumber).arg(exception));
410 QTextCursor cursor = scriptWidget_->currentScript->textCursor();
411 cursor.setPosition(0);
412 cursor.movePosition ( QTextCursor::Down, QTextCursor::MoveAnchor, lineNumber - 1 );
413 scriptWidget_->currentScript->setTextCursor(cursor);
415 scriptWidget_->currentScript->highLightErrorLine(lineNumber);
417 lastProblemLine_ = lineNumber;
418 lastError_ = exception;
423 if ( OpenFlipper::Options::gui() && !error)
424 statusBar_->clearMessage();
427 OpenFlipper::Options::scripting(
false);
430 void ScriptingPlugin::slotExecuteFileScript( QString _filename ) {
433 QFile data(_filename);
434 if (data.open(QFile::ReadOnly)) {
435 QTextStream input(&data);
437 script.append(input.readLine() +
"\n");
438 }
while (!input.atEnd());
440 if ( OpenFlipper::Options::gui() )
441 scriptWidget_->currentScript->setPlainText(script);
444 OpenFlipper::Options::currentScriptDir( _filename.section(OpenFlipper::Options::dirSeparator(), 0, -2) );
446 slotExecuteScript(script);
449 emit log(
LOGERR,tr(
"Unable to open script file!"));
452 void ScriptingPlugin::slotExecuteScriptButton() {
453 slotExecuteScript( scriptWidget_->currentScript->toPlainText() );
458 #ifdef ENABLE_SCRIPT_DEBUGGER 459 #ifdef QT_SCRIPTTOOLS_LIB 460 QScriptEngine* engine;
461 emit getScriptingEngine( engine );
463 if ( debuggerButton_->isChecked() ) {
464 debugger_->attachTo(engine);
475 QString ScriptingPlugin::mangleScript(QString _input ) {
478 QStringList functions;
479 emit getAvailableFunctions( functions );
481 std::cerr <<
"Todo : mangle script " << std::endl;
488 if ( OpenFlipper::Options::nogui() )
493 timer.setSingleShot(
true);
494 timer.start( _seconds * 1000 );
496 while (timer.isActive() )
497 QApplication::processEvents();
503 if ( OpenFlipper::Options::nogui() )
508 timer.setSingleShot(
true);
509 timer.start( _mseconds );
511 while (timer.isActive() )
512 QApplication::processEvents();
517 frameTime_.restart();
521 int elapsed = frameTime_.elapsed();
524 if ( elapsed < _mseconds ) {
525 sleepmsecs( _mseconds - elapsed );
529 frameTime_.restart();
535 if ( OpenFlipper::Options::nogui() )
540 box.addButton(tr(
"Continue"),QMessageBox::AcceptRole);
541 box.setText(tr(
"Script execution has been interrupted"));
542 box.setIcon(QMessageBox::Information);
543 box.setWindowModality(Qt::NonModal);
544 box.setWindowTitle(tr(
"Continue?"));
545 box.setWindowFlags( box.windowFlags() | Qt::WindowStaysOnTopHint);
548 while ( box.isVisible() )
549 QApplication::processEvents();
554 if ( OpenFlipper::Options::nogui() )
560 box.addButton(tr(
"Continue"),QMessageBox::AcceptRole);
562 box.setIcon(QMessageBox::Information);
563 box.setWindowModality(Qt::NonModal);
564 box.setWindowTitle(tr(
"Continue?"));
565 box.setWindowFlags( box.windowFlags() | Qt::WindowStaysOnTopHint);
570 while ( box.isVisible() )
571 QApplication::processEvents();
576 void ScriptingPlugin::slotLoadScript(){
578 QString lastOpened =
OpenFlipperSettings().
value(
"Scripting/CurrentDir",OpenFlipper::Options::currentScriptDirStr()).toString();
580 QString filename = QFileDialog::getOpenFileName(0,
581 tr(
"Load Script"),lastOpened , tr(
"Script Files (*.ofs)"));
586 QFileInfo info (filename);
589 slotLoadScript(filename);
592 void ScriptingPlugin::slotLoadScript( QString _filename ) {
598 if ( OpenFlipper::Options::gui() ) {
599 scriptWidget_->currentScript->clear();
601 QFile data(_filename);
603 if (data.open(QFile::ReadOnly)) {
604 QTextStream input(&data);
606 scriptWidget_->currentScript->appendPlainText(input.readLine());
607 }
while (!input.atEnd());
609 lastFile_ = _filename;
610 OpenFlipper::Options::currentScriptDir( QFileInfo(_filename).absolutePath() );
612 scriptWidget_->actionSave_Script->setEnabled(
false );
614 scriptWidget_->show();
620 void ScriptingPlugin::slotSaveScript(){
622 QFile file(lastFile_);
628 if (file.open(QFile::WriteOnly)) {
629 QTextStream output(&file);
630 output << scriptWidget_->currentScript->toPlainText();
632 scriptWidget_->actionSave_Script->setEnabled(
false );
636 void ScriptingPlugin::slotSaveScriptAs(){
637 QString lastOpened =
OpenFlipperSettings().
value(
"Scripting/CurrentDir",OpenFlipper::Options::currentScriptDirStr()).toString();
639 QString filename = QFileDialog::getSaveFileName(scriptWidget_,
640 tr(
"Save Script"),lastOpened, tr(
"Script Files (*.ofs)"));
642 if (filename ==
"")
return;
644 QFileInfo info (filename);
648 QFile data(filename);
652 QFileInfo fi(filename);
653 if (fi.completeSuffix() ==
""){
654 filename = filename +
".ofs";
655 data.setFileName(filename);
660 if (data.open(QFile::WriteOnly)) {
661 QTextStream output(&data);
662 output << scriptWidget_->currentScript->toPlainText();
665 lastFile_ = filename;
666 OpenFlipper::Options::currentScriptDir( QFileInfo(filename).absolutePath() );
668 scriptWidget_->actionSave_Script->setEnabled(
false );
671 void ScriptingPlugin::slotFunctionClicked(QListWidgetItem * _item)
677 QString slotDescription;
679 QStringList descriptions;
681 emit getDescription(_item->text(), slotDescription, params, descriptions);
683 if ( !slotDescription.isEmpty() ){
685 if (descriptionLabels_.count() > 0){
687 for (
int i = 0; i < descriptionLabels_.count(); i++){
688 descrLayout_->removeWidget( descriptionLabels_[i] );
689 delete descriptionLabels_[i];
691 descriptionLabels_.clear();
693 descrLayout_ =
new QVBoxLayout();
695 QLabel* lSlotName =
new QLabel(
"<B>" + _item->text() +
"</B>");
696 QLabel* lDescription =
new QLabel(slotDescription);
697 lDescription->setWordWrap(
true);
699 descrLayout_->addWidget(lSlotName);
700 descrLayout_->addWidget(lDescription);
702 descriptionLabels_.append(lSlotName);
703 descriptionLabels_.append(lDescription);
705 if ( params.count() == descriptions.count() ){
708 QString typeStr = _item->text().section(
"(",1,1).section(
")",0,0);
709 QStringList types = typeStr.split(
",");
711 if (types.count() == params.count()){
713 for(
int p=0; p < params.count(); p++ ){
714 QLabel* param =
new QLabel(
"<B>" + types[p] +
" " + params[p] +
":</B>" );
715 QLabel* descr =
new QLabel(descriptions[p]);
716 descr->setWordWrap(
true);
717 descrLayout_->addWidget(param);
718 descrLayout_->addWidget(descr);
720 descriptionLabels_.append(param);
721 descriptionLabels_.append(descr);
729 scriptWidget_->description->setLayout( descrLayout_ );
732 scriptWidget_->description->setVisible( !slotDescription.isEmpty() );
735 void ScriptingPlugin::slotFunctionDoubleClicked(QListWidgetItem * _item)
737 scriptWidget_->currentScript->insertPlainText( _item->text() );
742 if ( OpenFlipper::Options::nogui() )
750 OpenFlipper::Options::currentScriptDir(
"" );
754 scriptWidget_->currentScript->setPlainText(_code);
758 if ( OpenFlipper::Options::nogui() )
761 scriptWidget_->currentScript->clear();
void hideScriptWidget()
Hide the script editor widget.
void pluginsInitialized()
void slotHighlightError()
Called when an error is detected when checking the syntax.
void showScriptWidget()
Show the script editor widget.
void sleepmsecs(int _mseconds)
Sleeps for some mseconds in script execution ( Gui will remain functional)
void clearEditor()
Clear the editor window Clears the script editor window.
void waitFrameEnd(int _mseconds)
wait until _mseconds have passed since frameStart (if more time has passed, it will return immediatel...
void slotDebuggerButton()
Triggered by the debugger button.
void sleep(int _seconds)
Sleeps for some seconds in script execution ( Gui will remain functional)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
void frameStart()
Marks the current time as the frame start ( Use wait sleepFrameLength to wait until _mseconds have pa...
void showScriptInEditor(QString _code)
Show the given Code in the script editor.
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
void slotExecuteScript(QString _script)
void slotScriptChanged()
Called everytime the text in the scriptingwidget is changed by the user.