ScriptingPlugin.cc 24.4 KB
Newer Older
1
/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
2
3
*                                                                            *
*                              OpenFlipper                                   *
Martin Schultz's avatar
Martin Schultz committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
 *           Department of Computer Graphics and Multimedia                  *
 *                          All rights reserved.                             *
 *                            www.openflipper.org                            *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenFlipper.                                         *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
 *                                                                           *
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
 *                                                                           *
 * 2. Redistributions in binary form must reproduce the above copyright      *
 *    notice, this list of conditions and the following disclaimer in the    *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. Neither the name of the copyright holder nor the names of its          *
 *    contributors may be used to endorse or promote products derived from   *
 *    this software without specific prior written permission.               *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
Jan Möbius's avatar
Jan Möbius committed
39
*                                                                            *
40
41
42
\*===========================================================================*/

/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
43
44
45
46
47
*                                                                            *
*   $Revision$                                                       *
*   $LastChangedBy$                                                *
*   $Date$                     *
*                                                                            *
48
49
\*===========================================================================*/

Jan Möbius's avatar
 
Jan Möbius committed
50
51
52
53
#include "ScriptingPlugin.hh"

#include "OpenFlipper/common/GlobalOptions.hh"

54
#if QT_VERSION >= 0x050000
55
56
57
#else
#include <QtGui>
#endif
58
59


Jan Möbius's avatar
Jan Möbius committed
60
61
62
63
64
65
66
67
68
69
ScriptingPlugin::ScriptingPlugin() :
   lastProblemLine_(0),
   lastError_(""),
   errorTimer_(0),
   descrLayout_(0),
   scriptWidget_(0),
   statusBar_(0),
   highlighterCurrent_(0),
   highlighterLive_(0),
   highlighterList_(0),
70
   lastFile_(""),
Jan Möbius's avatar
Jan Möbius committed
71
   scriptPath_(""),
72
   debuggerButton_(0)
73
#ifdef ENABLE_SCRIPT_DEBUGGER
74
  #ifdef QT_SCRIPTTOOLS_LIB
75
   ,debugger_(0)
76
  #endif
77
#endif
Jan Möbius's avatar
Jan Möbius committed
78
{
Jan Möbius's avatar
 
Jan Möbius committed
79
80
81
82
83
84
85
86
87
88
89

}

void ScriptingPlugin::pluginsInitialized() {

  if ( OpenFlipper::Options::nogui() )
    return;

  ///@todo register objectid variable

  // Scriping Menu
90
  QMenu *scriptingMenu;
Jan Möbius's avatar
 
Jan Möbius committed
91

92
  emit getMenubarMenu(tr("&Scripting"), scriptingMenu, true );
Jan Möbius's avatar
 
Jan Möbius committed
93
94

  QIcon icon;
Dirk Wilden's avatar
Dirk Wilden committed
95
  QAction* showWidget = scriptingMenu->addAction( tr("Show script editor") );
Jan Möbius's avatar
 
Jan Möbius committed
96
97
98
99
100
101
102
  icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"scriptEditor.png");
  showWidget->setIcon(icon);
  connect( showWidget, SIGNAL( triggered() ) ,
           this      , SLOT( showScriptWidget() ));

  scriptWidget_ = new ScriptWidget();

Jan Möbius's avatar
Jan Möbius committed
103
104
105

  QString iconPath = OpenFlipper::Options::iconDirStr() + OpenFlipper::Options::dirSeparator();

Jan Möbius's avatar
 
Jan Möbius committed
106
107
  scriptWidget_->setWindowIcon( OpenFlipper::Options::OpenFlipperIcon() );

Jan Möbius's avatar
Jan Möbius committed
108
  icon.addFile(iconPath+"document-open.png");
Jan Möbius's avatar
 
Jan Möbius committed
109
110
  scriptWidget_->actionLoad_Script->setIcon(icon);

Jan Möbius's avatar
Jan Möbius committed
111
  icon.addFile(iconPath+"document-save.png");
Jan Möbius's avatar
 
Jan Möbius committed
112
113
  scriptWidget_->actionSave_Script->setIcon(icon);

Jan Möbius's avatar
Jan Möbius committed
114
  icon.addFile(iconPath+"document-save-as.png");
Jan Möbius's avatar
 
Jan Möbius committed
115
116
  scriptWidget_->actionSave_Script_As->setIcon(icon);

Jan Möbius's avatar
Jan Möbius committed
117
  icon.addFile(iconPath+"window-close.png");
Jan Möbius's avatar
 
Jan Möbius committed
118
119
  scriptWidget_->actionClose->setIcon(icon);

120
121
122
123
124
  // ==================================================================
  // Add a toolbar
  // ==================================================================

  QToolBar* toolBar = new QToolBar(tr("Scripting Toolbar"));
Jan Möbius's avatar
Jan Möbius committed
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

  QAction* openButton = new QAction(QIcon(iconPath + "document-open.png"), "Open", toolBar);
  toolBar->addAction(openButton);
  connect (openButton, SIGNAL( triggered() ), this, SLOT( slotLoadScript() ) );

  QAction* saveButton = new QAction(QIcon(iconPath + "document-save.png"), "Save", toolBar);
  toolBar->addAction(saveButton);
  connect (saveButton, SIGNAL( triggered() ), this, SLOT( slotSaveScript() ) );

  QAction* saveAsButton = new QAction(QIcon(iconPath + "document-save-as.png"), "Save as", toolBar);
  toolBar->addAction(saveAsButton);
  connect (saveAsButton, SIGNAL( triggered() ), this, SLOT( slotSaveScriptAs() ) );

  toolBar->addSeparator();

140
141
142
143
  debuggerButton_ = new QAction(QIcon(iconPath + "script-debugger.png"), "Enable Debugger", toolBar);
  debuggerButton_->setCheckable(true);
  toolBar->addAction(debuggerButton_);

144
#ifdef ENABLE_SCRIPT_DEBUGGER
145
146
147
148
149
150
151
152
  if ( OpenFlipperSettings().value("Scripting/QtScriptDebugger",true).toBool() )
    debuggerButton_->setChecked(true);
  else
    debuggerButton_->setChecked(false);

  connect (debuggerButton_, SIGNAL( triggered() ), this, SLOT( slotDebuggerButton() ) );
#else
  debuggerButton_->setEnabled(false);
153
  debuggerButton_->setToolTip(tr("QtScriptTools library not available. Debugger is not available!"));
154
155
156
157
#endif

  toolBar->addSeparator();

Jan Möbius's avatar
Jan Möbius committed
158
159
160
161
162
163
  QAction* executeButton = new QAction(QIcon(iconPath + "arrow-right.png"), "Execute", toolBar);
  toolBar->addAction(executeButton);
  connect (executeButton, SIGNAL( triggered() ), this, SLOT( slotExecuteScriptButton() ) );

  scriptWidget_->addToolBar(toolBar);

164
165
166
167
168
169
170
171
172
173
  // ==================================================================
  // Create a status bar
  // ==================================================================

  statusBar_ = new QStatusBar();

  scriptWidget_->setStatusBar( statusBar_ );

  // ==================================================================

Jan Möbius's avatar
 
Jan Möbius committed
174
175
176
177
178
179
180
181
182
183
184
  scriptWidget_->hide();

  scriptWidget_->resize(scriptWidget_->width() , std::min(QApplication::desktop()->screenGeometry().height() - 150 , 800) );

  connect (scriptWidget_->actionLoad_Script, SIGNAL( triggered() ), this, SLOT( slotLoadScript() ) );
  scriptWidget_->actionLoad_Script->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_O) );
  connect (scriptWidget_->actionSave_Script, SIGNAL( triggered() ), this, SLOT( slotSaveScript() ) );
  scriptWidget_->actionSave_Script->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_S) );
  connect (scriptWidget_->actionSave_Script_As, SIGNAL( triggered() ), this, SLOT( slotSaveScriptAs() ) );
  connect (scriptWidget_->actionClose, SIGNAL( triggered() ), scriptWidget_, SLOT( close() ) );

Jan Möbius's avatar
Jan Möbius committed
185
  connect (scriptWidget_->currentScript, SIGNAL( textChanged() ), this, SLOT( slotScriptChanged() ) );
Jan Möbius's avatar
 
Jan Möbius committed
186

187
  connect (scriptWidget_->functionList, SIGNAL( currentItemChanged  (QListWidgetItem*, QListWidgetItem*) ),
Jan Möbius's avatar
 
Jan Möbius committed
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
           this,                          SLOT( slotFunctionClicked(QListWidgetItem*) ));
  connect (scriptWidget_->functionList, SIGNAL( itemDoubleClicked(QListWidgetItem*) ),
           this,                          SLOT( slotFunctionDoubleClicked(QListWidgetItem*) ));

  //filter
  connect (scriptWidget_->filterButton, SIGNAL( clicked() ),
           this,                          SLOT( slotApplyFilter() ));
  connect (scriptWidget_->resetButton, SIGNAL( clicked() ),
           scriptWidget_->functionList,  SLOT( reset() ));
  connect (scriptWidget_->resetButton, SIGNAL( clicked() ),
           scriptWidget_->filterEdit,  SLOT( clear() ));
  connect (scriptWidget_->functionList, SIGNAL(getDescription(QString,QString&,QStringList&,QStringList&)),
           this                       , SIGNAL(getDescription(QString,QString&,QStringList&,QStringList&)));

  scriptWidget_->description->setVisible( false );

204
  highlighterCurrent_ = new Highlighter( scriptWidget_->currentScript->document() );
Jan Möbius's avatar
 
Jan Möbius committed
205
206
207
  highlighterLive_    = new Highlighter( scriptWidget_->liveEdit );
//   highlighterList_    = new Highlighter( scriptWidget_->functionList  );
  frameTime_.start();
Jan Möbius's avatar
Jan Möbius committed
208
209
210
211
212
213
214
215


  // Timer for syntax error while editing. If the Syntax is not correct
  // And the text does not change for a specified time, the line will be highlighted
  // And a message printed to the status bar
  errorTimer_ = new QTimer();
  errorTimer_->setSingleShot(true);
  connect(errorTimer_,SIGNAL(timeout()),this,SLOT(slotHighlightError()));
216
217
218
219
220

  // ==================================================================
  // Setup scripting debugger if available
  // ==================================================================

221
#ifdef ENABLE_SCRIPT_DEBUGGER
222
 #ifdef QT_SCRIPTTOOLS_LIB
223
224
225
226
  QScriptEngine* engine;
  emit getScriptingEngine( engine  );
  debugger_ = new QScriptEngineDebugger;

227
  if ( OpenFlipperSettings().value("Scripting/QtScriptDebugger",false).toBool() )
228
    debugger_->attachTo(engine);
229
 #endif
230
#endif
Jan Möbius's avatar
 
Jan Möbius committed
231
232
233
234
235
236
}

void ScriptingPlugin::slotApplyFilter(){
  scriptWidget_->functionList->filter( scriptWidget_->filterEdit->text() );
}

Jan Möbius's avatar
Jan Möbius committed
237
void ScriptingPlugin::slotScriptChanged(){
Jan Möbius's avatar
 
Jan Möbius committed
238
  scriptWidget_->actionSave_Script->setEnabled( true );
Jan Möbius's avatar
Jan Möbius committed
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

  // Stop timers, as the text changed!
  errorTimer_->stop();

  // Check the current script for syntax
  const QString script = scriptWidget_->currentScript->toPlainText();
  QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax ( script );

  switch (syntaxCheck.state() ) {
    case QScriptSyntaxCheckResult::Error :
      lastProblemLine_ = syntaxCheck.errorLineNumber();
      lastError_       = syntaxCheck.errorMessage();
      errorTimer_->start(500);
      break;
    case QScriptSyntaxCheckResult::Valid :
      break;
Jan Möbius's avatar
Jan Möbius committed
255
    default :
Jan Möbius's avatar
Jan Möbius committed
256
      break;
Jan Möbius's avatar
Jan Möbius committed
257
258
259
260
261
262
  }
}

void ScriptingPlugin::slotHighlightError() {
  scriptWidget_->currentScript->highLightErrorLine(lastProblemLine_);
  statusBar_->showMessage(lastError_,5000);
Jan Möbius's avatar
 
Jan Möbius committed
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
}

void ScriptingPlugin::showScriptWidget( ) {
  if ( OpenFlipper::Options::nogui() )
    return;

  scriptWidget_->show();

  // Update list of available functions
  QStringList completeList;
  emit getAvailableFunctions( completeList  );

  QStringList plugins;
  QStringList functions;

  scriptWidget_->functionList->clear( );

  //Update Highlighters
  for ( int i = 0  ; i <  completeList.size() ; ++i) {

    QString plugin   = completeList[i].section('.',0,0);
284
285
286
287
288
289

    // Global functions start with - and are not added as plugins!
    if (plugin != "-") {
      if ( ! plugins.contains( plugin ) )
        plugins.push_back( plugin );
    }
Jan Möbius's avatar
 
Jan Möbius committed
290
291
292
293
294
295
296


    QString function = completeList[i].section('.',1,1);
    function         = function.section('(',0,0);
    if ( ! functions.contains( function ) )
      functions.push_back( function );

297
298
299
300
301
    // Either write the whole string or cut the "-." for global functions
    if ( plugin != "-")
      scriptWidget_->functionList->addItem( completeList[i] );
    else
      scriptWidget_->functionList->addItem( completeList[i].right(completeList[i].size() - 2) );
Jan Möbius's avatar
 
Jan Möbius committed
302
303
304

  }

305
306
307
  // Sort the available functions
  scriptWidget_->functionList->sortItems ( );

Jan Möbius's avatar
 
Jan Möbius committed
308
309
310
311
312
313
314
315
316
317
  highlighterCurrent_->pluginPatterns_   = plugins;
  highlighterCurrent_->functionPatterns_ = functions;
  highlighterCurrent_->update();
  highlighterCurrent_->rehighlight();

  highlighterLive_->pluginPatterns_      = plugins;
  highlighterLive_->functionPatterns_    = functions;
  highlighterLive_->update();
  highlighterLive_->rehighlight();

318
319
320
  // Bring it to foreground
  scriptWidget_->raise();

Jan Möbius's avatar
 
Jan Möbius committed
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
}

void ScriptingPlugin::hideScriptWidget( ) {
  if ( OpenFlipper::Options::nogui() )
    return;

  scriptWidget_->hide();
}

void ScriptingPlugin::slotScriptInfo( QString _pluginName , QString _functionName  ) {

  if ( OpenFlipper::Options::scripting() || OpenFlipper::Options::nogui()  )
    return;

  scriptWidget_->liveEdit->append( _pluginName + "." + _functionName );

  QScrollBar* bar = scriptWidget_->liveEdit->verticalScrollBar();
  bar->setValue(bar->maximum());
}

void ScriptingPlugin::slotExecuteScript( QString _script ) {
342
343
344
345

  if ( OpenFlipper::Options::gui())
    statusBar_->showMessage(tr("Executing Script"));

Jan Möbius's avatar
 
Jan Möbius committed
346
347
348
349
350
351
352
  QScriptEngine* engine;
  emit getScriptingEngine( engine  );

  /// Switch scripting mode on
  OpenFlipper::Options::scripting(true);

  // Get the filename of the script and set it in the scripting environment
Jan Möbius's avatar
Jan Möbius committed
353
  engine->globalObject().setProperty("ScriptPath",OpenFlipper::Options::currentScriptDirStr());
Jan Möbius's avatar
 
Jan Möbius committed
354

355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  // Check if the script contains include statements
  if (_script.contains(QRegExp("^include <")) ) {

    // Split input script into lines
    QStringList script = _script.split(QRegExp("[\r\n]"),QString::SkipEmptyParts);

    // Find first include statement
    int include_index = script.indexOf(QRegExp("^include.*"));

    while ( include_index != -1) {

      QString include_statement =  script[include_index];

      // Extract the file path of the include
      include_statement.remove(QRegExp("^include") );
      include_statement.remove("<" );
      include_statement.remove(">" );
      include_statement = include_statement.trimmed();

      // Replace the ScriptPath component
      include_statement.replace("ScriptPath",OpenFlipper::Options::currentScriptDirStr());

      QFile includeFile(include_statement);

      if (!includeFile.exists() ) {
        emit log(LOGERR,"Script file include not found : " + include_statement + " from " + script[include_index] );
        return;
      } else {

        if (!includeFile.open(QFile::ReadOnly | QFile::Text))  {
          emit log(LOGERR,"Unable to open file : " + include_statement);
          return;
        }

        QTextStream in(&includeFile);
        script[include_index] = in.readAll();
        includeFile.close();
      }

      // Recombine all script components
      _script = script.join("\n");

      // Check for next occurence of an include statement
      include_index = script.indexOf(QRegExp("^include.*"));

    }

  }

404
  // Execute the script
Jan Möbius's avatar
 
Jan Möbius committed
405
  engine->evaluate( _script );
406
407
408

  // Catch errors and print some reasonable error message to log and statusbar
  bool error = false;
Jan Möbius's avatar
 
Jan Möbius committed
409
  if ( engine->hasUncaughtException() ) {
410
    error = true;
Jan Möbius's avatar
 
Jan Möbius committed
411
412
    QScriptValue result = engine->uncaughtException();
    QString exception = result.toString();
413
414
415
    int lineNumber = engine->uncaughtExceptionLineNumber();
    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));
418
419
420
421
422
423
424
425

        // Get cursor and move it to the line containing the error
        QTextCursor cursor = scriptWidget_->currentScript->textCursor();
        cursor.setPosition(0);
        cursor.movePosition ( QTextCursor::Down, QTextCursor::MoveAnchor, lineNumber - 1 );
        scriptWidget_->currentScript->setTextCursor(cursor);

        scriptWidget_->currentScript->highLightErrorLine(lineNumber);
Jan Möbius's avatar
Jan Möbius committed
426
427
428
429

        lastProblemLine_ = lineNumber;
        lastError_       = exception;

430
    }
Jan Möbius's avatar
 
Jan Möbius committed
431
432
  }

433
434
435
  if ( OpenFlipper::Options::gui() && !error)
    statusBar_->clearMessage();

Jan Möbius's avatar
 
Jan Möbius committed
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
  /// Switch scripting mode off
  OpenFlipper::Options::scripting(false);
}

void ScriptingPlugin::slotExecuteFileScript( QString _filename ) {
  QString script;

  QFile data(_filename);
  if (data.open(QFile::ReadOnly)) {
    QTextStream input(&data);
    do {
      script.append(input.readLine() + "\n");
    } while (!input.atEnd());

    if ( OpenFlipper::Options::gui() )
451
      scriptWidget_->currentScript->setPlainText(script);
Jan Möbius's avatar
 
Jan Möbius committed
452

Jan Möbius's avatar
Jan Möbius committed
453
454
455
    // Set the correct execution environment
    OpenFlipper::Options::currentScriptDir( _filename.section(OpenFlipper::Options::dirSeparator(), 0, -2) );

Jan Möbius's avatar
 
Jan Möbius committed
456
457
458
    slotExecuteScript(script);

  } else
Dirk Wilden's avatar
Dirk Wilden committed
459
    emit log(LOGERR,tr("Unable to open script file!"));
Jan Möbius's avatar
 
Jan Möbius committed
460
461
462
463
464
465
}

void ScriptingPlugin::slotExecuteScriptButton() {
  slotExecuteScript( scriptWidget_->currentScript->toPlainText() );
}

466
467
void ScriptingPlugin::slotDebuggerButton() {

468
#ifdef ENABLE_SCRIPT_DEBUGGER
469
 #ifdef QT_SCRIPTTOOLS_LIB
470
471
472
473
474
475
476
477
478
479
  QScriptEngine* engine;
  emit getScriptingEngine( engine  );

  if ( debuggerButton_->isChecked() ) {
    debugger_->attachTo(engine);
  } else {
    debugger_->detach();
  }

  OpenFlipperSettings().setValue("Scripting/QtScriptDebugger",debuggerButton_->isChecked());
480
 #endif
481
482
483
484
#endif

}

Jan Möbius's avatar
 
Jan Möbius committed
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
QString ScriptingPlugin::mangleScript(QString _input ) {

  // Update list of available functions
  QStringList functions;
  emit getAvailableFunctions( functions  );

  std::cerr << "Todo : mangle script " << std::endl;
  return _input;

}

void ScriptingPlugin::sleep( int _seconds ) {

  if ( OpenFlipper::Options::nogui() )
    return;

  QTimer timer;

  timer.setSingleShot(true);
  timer.start( _seconds * 1000 );

  while (timer.isActive() )
    QApplication::processEvents();

}

void ScriptingPlugin::sleepmsecs( int _mseconds ) {

  if ( OpenFlipper::Options::nogui() )
    return;

  QTimer timer;

  timer.setSingleShot(true);
  timer.start( _mseconds );

  while (timer.isActive() )
    QApplication::processEvents();

}

void ScriptingPlugin::frameStart( ) {
  frameTime_.restart();
}

void ScriptingPlugin::waitFrameEnd( int _mseconds ) {
  int elapsed = frameTime_.elapsed();

  // Wait remaining time
  if ( elapsed < _mseconds ) {
    sleepmsecs( _mseconds - elapsed );
  }

  // restart timer
  frameTime_.restart();

}


void ScriptingPlugin::waitContinue( ) {
  if ( OpenFlipper::Options::nogui() )
    return;

  QMessageBox box;

Dirk Wilden's avatar
Dirk Wilden committed
550
551
  box.addButton(tr("Continue"),QMessageBox::AcceptRole);
  box.setText(tr("Script execution has been interrupted"));
Jan Möbius's avatar
 
Jan Möbius committed
552
553
  box.setIcon(QMessageBox::Information);
  box.setWindowModality(Qt::NonModal);
Dirk Wilden's avatar
Dirk Wilden committed
554
  box.setWindowTitle(tr("Continue?"));
Jan Möbius's avatar
 
Jan Möbius committed
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
  box.setWindowFlags( box.windowFlags() | Qt::WindowStaysOnTopHint);
  box.show();

  while ( box.isVisible() )
    QApplication::processEvents();

}

void ScriptingPlugin::waitContinue( QString _msg, int _x, int _y ) {
  if ( OpenFlipper::Options::nogui() )
    return;

  QMessageBox box;


Dirk Wilden's avatar
Dirk Wilden committed
570
  box.addButton(tr("Continue"),QMessageBox::AcceptRole);
Jan Möbius's avatar
 
Jan Möbius committed
571
572
573
  box.setText(_msg);
  box.setIcon(QMessageBox::Information);
  box.setWindowModality(Qt::NonModal);
Dirk Wilden's avatar
Dirk Wilden committed
574
  box.setWindowTitle(tr("Continue?"));
Jan Möbius's avatar
 
Jan Möbius committed
575
576
577
578
579
580
581
582
583
584
585
586
  box.setWindowFlags( box.windowFlags() | Qt::WindowStaysOnTopHint);
  if(_x!=-1 && _y!=-1)
    box.move(_x,_y);
  box.show();

  while ( box.isVisible() )
    QApplication::processEvents();

}


void ScriptingPlugin::slotLoadScript(){
587
588
589

  QString lastOpened = OpenFlipperSettings().value("Scripting/CurrentDir",OpenFlipper::Options::currentScriptDirStr()).toString();

Jan Möbius's avatar
 
Jan Möbius committed
590
  QString filename = QFileDialog::getOpenFileName(0,
591
     tr("Load Script"),lastOpened , tr("Script Files (*.ofs)"));
Jan Möbius's avatar
 
Jan Möbius committed
592
593
594

  if (filename == "")
    return;
595
  
596
597
598
  QFileInfo info (filename);
  OpenFlipperSettings().setValue("Scripting/CurrentDir",info.path());

599
600
  slotLoadScript(filename);
}
Jan Möbius's avatar
 
Jan Möbius committed
601

602
603
604
605
606
607
608
609
610
611
612
613
614
615
void ScriptingPlugin::slotLoadScript( QString _filename ) {
  
  if (_filename == "")
      return;
    
  // Check if we are in gui mode. Otherwise just ignore this call
  if ( OpenFlipper::Options::gui() ) {
    scriptWidget_->currentScript->clear();
  
    QFile data(_filename);
    
    if (data.open(QFile::ReadOnly)) {
      QTextStream input(&data);
      do {
616
        scriptWidget_->currentScript->appendPlainText(input.readLine());
617
618
619
620
621
622
623
624
625
626
627
      } while (!input.atEnd());
      
      lastFile_ = _filename;
      OpenFlipper::Options::currentScriptDir( QFileInfo(_filename).absolutePath() );
      
      scriptWidget_->actionSave_Script->setEnabled( false );
      
      scriptWidget_->show();
    }
  }
  
Jan Möbius's avatar
 
Jan Möbius committed
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
}

void ScriptingPlugin::slotSaveScript(){

  QFile file(lastFile_);

  if ( !file.exists())
    slotSaveScriptAs();
  else{
    //write script to file
    if (file.open(QFile::WriteOnly)) {
      QTextStream output(&file);
      output << scriptWidget_->currentScript->toPlainText();
    }
    scriptWidget_->actionSave_Script->setEnabled( false );
  }
}

void ScriptingPlugin::slotSaveScriptAs(){
647
648
  QString lastOpened = OpenFlipperSettings().value("Scripting/CurrentDir",OpenFlipper::Options::currentScriptDirStr()).toString();

Jan Möbius's avatar
 
Jan Möbius committed
649
  QString filename = QFileDialog::getSaveFileName(scriptWidget_,
650
      tr("Save Script"),lastOpened, tr("Script Files (*.ofs)"));
Jan Möbius's avatar
 
Jan Möbius committed
651
652
653

  if (filename == "") return;

654
655
656
657
  QFileInfo info (filename);
  OpenFlipperSettings().setValue("Scripting/CurrentDir",info.path());


Jan Möbius's avatar
 
Jan Möbius committed
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
  QFile data(filename);

  //perhaps add an extension
  if (!data.exists()){
    QFileInfo fi(filename);
    if (fi.completeSuffix() == ""){
      filename = filename + ".ofs";
      data.setFileName(filename);
    }
  }

  //write script to file
  if (data.open(QFile::WriteOnly)) {
    QTextStream output(&data);
    output << scriptWidget_->currentScript->toPlainText();
Jan Möbius's avatar
Jan Möbius committed
673
  }
Jan Möbius's avatar
 
Jan Möbius committed
674

Jan Möbius's avatar
Jan Möbius committed
675
  lastFile_ = filename;
Jan Möbius's avatar
 
Jan Möbius committed
676
  OpenFlipper::Options::currentScriptDir( QFileInfo(filename).absolutePath() );
Jan Möbius's avatar
Jan Möbius committed
677

Jan Möbius's avatar
 
Jan Möbius committed
678
679
680
681
682
683
  scriptWidget_->actionSave_Script->setEnabled( false );
}

void ScriptingPlugin::slotFunctionClicked(QListWidgetItem * _item)
{

684
685
686
  if ( _item == 0)
    return;

Jan Möbius's avatar
 
Jan Möbius committed
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
  QString slotDescription;
  QStringList params;
  QStringList descriptions;

  emit getDescription(_item->text(), slotDescription, params, descriptions);

  if ( !slotDescription.isEmpty() ){

    if (descriptionLabels_.count() > 0){
      //first remove old stuff
      for (int i = 0; i < descriptionLabels_.count(); i++){
        descrLayout_->removeWidget( descriptionLabels_[i] );
        delete descriptionLabels_[i];
      }
      descriptionLabels_.clear();
    }else
      descrLayout_ = new QVBoxLayout();

    QLabel* lSlotName = new QLabel("<B>" + _item->text() + "</B>");
    QLabel* lDescription = new QLabel(slotDescription);
    lDescription->setWordWrap(true);

    descrLayout_->addWidget(lSlotName);
    descrLayout_->addWidget(lDescription);

    descriptionLabels_.append(lSlotName);
    descriptionLabels_.append(lDescription);

    if ( params.count() == descriptions.count() ){

      //get parameter-types from function-name
      QString typeStr = _item->text().section("(",1,1).section(")",0,0);
      QStringList types = typeStr.split(",");

      if (types.count() == params.count()){

        for(int p=0; p < params.count(); p++ ){
          QLabel* param = new QLabel("<B>" + types[p] + " " + params[p] + ":</B>" );
          QLabel* descr = new QLabel(descriptions[p]);
          descr->setWordWrap(true);
          descrLayout_->addWidget(param);
          descrLayout_->addWidget(descr);

          descriptionLabels_.append(param);
          descriptionLabels_.append(descr);
        }

      }

    }


    scriptWidget_->description->setLayout( descrLayout_ );
  }

  scriptWidget_->description->setVisible( !slotDescription.isEmpty() );
}

void ScriptingPlugin::slotFunctionDoubleClicked(QListWidgetItem * _item)
{
  scriptWidget_->currentScript->insertPlainText( _item->text() );
}

750
751
752
753
754
void ScriptingPlugin::showScriptInEditor(QString _code)
{
  if ( OpenFlipper::Options::nogui() )
    return;

755
  /*
Jan Möbius's avatar
Jan Möbius committed
756
   * This is called from the VSI and other plugins with pure code
757
758
759
   * we do not want to overwrite any previously opened scripts
   */
  lastFile_ = "";
Jan Möbius's avatar
Jan Möbius committed
760
  OpenFlipper::Options::currentScriptDir( "" );
761

762
763
  showScriptWidget ();

764
  scriptWidget_->currentScript->setPlainText(_code);
765
766
}

767
void ScriptingPlugin::clearEditor() {
768
769
770
  if ( OpenFlipper::Options::nogui() )
     return;

771
772
773
  scriptWidget_->currentScript->clear();
}

Matthias Möller's avatar
Matthias Möller committed
774
775
776
#if QT_VERSION < 0x050000
  Q_EXPORT_PLUGIN2( skriptingplugin , ScriptingPlugin );
#endif
Jan Möbius's avatar
 
Jan Möbius committed
777