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();
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
void slotScriptChanged()
Called everytime the text in the scriptingwidget is changed by the user.
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
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 showScriptWidget()
Show the script editor widget.
void sleep(int _seconds)
Sleeps for some seconds in script execution ( Gui will remain functional)
void waitFrameEnd(int _mseconds)
wait until _mseconds have passed since frameStart (if more time has passed, it will return immediatel...
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
void clearEditor()
Clear the editor window Clears the script editor window.
void slotExecuteScript(QString _script)
void sleepmsecs(int _mseconds)
Sleeps for some mseconds in script execution ( Gui will remain functional)
void slotHighlightError()
Called when an error is detected when checking the syntax.
void hideScriptWidget()
Hide the script editor widget.
void slotDebuggerButton()
Triggered by the debugger button.
void pluginsInitialized()