Subversion Repositories Scribus

Rev

Rev 11892 | Rev 11976 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
1467 cbradney 7
#include "scriptercore.h"
8
 
10223 cbradney 9
#include <QGlobalStatic>
10
#include <QWidget>
11
#include <QString>
12
#include <QApplication>
13
#include <QMessageBox>
14
#include <QTextCodec>
9535 fschmid 15
#include <QByteArray>
8501 cbradney 16
#include <QPixmap>
1718 craig 17
#include <cstdlib>
18
 
2622 craig 19
#include "runscriptdialog.h"
1467 cbradney 20
#include "helpbrowser.h"
10862 cbradney 21
#include "propertiespalette.h" //TODO Move the calls to this to a signal
22
#include "pagepalette.h" //TODO Move the calls to this to a signal
3623 cbradney 23
#include "layers.h" //TODO Move the calls to this to a signal
10862 cbradney 24
#include "outlinepalette.h" //TODO Move the calls to this to a signal
1718 craig 25
#include "menumanager.h"
3254 craig 26
#include "pconsole.h"
1718 craig 27
#include "scraction.h"
5243 cbradney 28
#include "scribuscore.h"
1718 craig 29
#include "scpaths.h"
3934 cbradney 30
#include "selection.h"
1750 craig 31
#include "prefsfile.h"
32
#include "prefscontext.h"
33
#include "prefstable.h"
2834 cbradney 34
#include "prefsmanager.h"
1467 cbradney 35
 
2503 subik 36
ScripterCore::ScripterCore(QWidget* parent)
1718 craig 37
{
2503 subik 38
        pcon = new PythonConsole(parent);
1718 craig 39
        scrScripterActions.clear();
40
        scrRecentScriptActions.clear();
5051 subik 41
        returnString = "init";
1467 cbradney 42
 
9857 cbradney 43
        scrScripterActions.insert("scripterExecuteScript", new ScrAction(QObject::tr("&Execute Script..."), QKeySequence(), this));
44
        scrScripterActions.insert("scripterShowConsole", new ScrAction(QObject::tr("Show &Console"), QKeySequence(), this));
45
        scrScripterActions.insert("scripterAboutScript", new ScrAction(QObject::tr("&About Script..."), QKeySequence(), this));
1467 cbradney 46
 
1718 craig 47
        scrScripterActions["scripterShowConsole"]->setToggleAction(true);
11892 jghali 48
        scrScripterActions["scripterShowConsole"]->setChecked(false);
1718 craig 49
 
10725 jghali 50
        QObject::connect( scrScripterActions["scripterExecuteScript"], SIGNAL(triggered()) , this, SLOT(runScriptDialog()) );
1718 craig 51
        QObject::connect( scrScripterActions["scripterShowConsole"], SIGNAL(toggled(bool)) , this, SLOT(slotInteractiveScript(bool)) );
10725 jghali 52
        QObject::connect( scrScripterActions["scripterAboutScript"], SIGNAL(triggered()) , this, SLOT(aboutScript()) );
1718 craig 53
 
5243 cbradney 54
        SavedRecentScripts.clear();
55
        ReadPlugPrefs();
56
 
57
        QObject::connect(pcon, SIGNAL(runCommand()), this, SLOT(slotExecute()));
58
        QObject::connect(pcon, SIGNAL(paletteShown(bool)), this, SLOT(slotInteractiveScript(bool)));
59
}
60
 
61
ScripterCore::~ScripterCore()
62
{
63
        SavePlugPrefs();
10249 jghali 64
        delete pcon;
5243 cbradney 65
}
66
 
67
void ScripterCore::addToMainWindowMenu(ScribusMainWindow *mw)
68
{
69
        menuMgr = mw->scrMenuMgr;
1718 craig 70
        menuMgr->createMenu("Scripter", QObject::tr("&Script"));
10558 cbradney 71
        menuMgr->addMenuToMenuBarBefore("Scripter","Windows");
1718 craig 72
        menuMgr->createMenu("ScribusScripts", QObject::tr("&Scribus Scripts"), "Scripter");
73
        menuMgr->addMenuItem(scrScripterActions["scripterExecuteScript"], "Scripter");
74
        menuMgr->createMenu("RecentScripts", QObject::tr("&Recent Scripts"), "Scripter");
75
        menuMgr->addMenuSeparator("Scripter");
76
        menuMgr->addMenuItem(scrScripterActions["scripterShowConsole"], "Scripter");
77
        menuMgr->addMenuItem(scrScripterActions["scripterAboutScript"], "Scripter");
78
        buildScribusScriptsMenu();
79
        buildRecentScriptsMenu();
80
}
81
 
82
 
83
void ScripterCore::buildScribusScriptsMenu()
84
{
85
        QString pfad = ScPaths::instance().scriptDir();
1467 cbradney 86
        QString pfad2;
87
        pfad2 = QDir::convertSeparators(pfad);
6235 fschmid 88
        QDir ds(pfad2, "*.py", QDir::Name | QDir::IgnoreCase, QDir::Files | QDir::NoSymLinks);
1467 cbradney 89
        if ((ds.exists()) && (ds.count() != 0))
90
        {
91
                for (uint dc = 0; dc < ds.count(); ++dc)
92
                {
93
                        QFileInfo fs(ds[dc]);
10598 cbradney 94
                        QString strippedName=fs.baseName();
9857 cbradney 95
                        scrScripterActions.insert(strippedName, new ScrAction( ScrAction::RecentScript, QPixmap(), QPixmap(), strippedName, QKeySequence(), this));
10729 cbradney 96
                        connect( scrScripterActions[strippedName], SIGNAL(triggeredData(QString)), this, SLOT(StdScript(QString)) );
1718 craig 97
                        menuMgr->addMenuItem(scrScripterActions[strippedName], "ScribusScripts");
1467 cbradney 98
                }
99
        }
1718 craig 100
 
101
 
102
}
103
 
104
void ScripterCore::rebuildRecentScriptsMenu()
105
{
8501 cbradney 106
        for( QMap<QString, QPointer<ScrAction> >::Iterator it = scrRecentScriptActions.begin(); it!=scrRecentScriptActions.end(); ++it )
1718 craig 107
                menuMgr->removeMenuItem((*it), "RecentScripts");
108
 
109
        scrRecentScriptActions.clear();
8562 jghali 110
        uint max = qMin(PrefsManager::instance()->appPrefs.RecentDCount, RecentScripts.count());
1718 craig 111
        for (uint m = 0; m < max; ++m)
1467 cbradney 112
        {
1718 craig 113
                QString strippedName=RecentScripts[m];
114
                strippedName.remove(QDir::separator());
9857 cbradney 115
                scrRecentScriptActions.insert(strippedName, new ScrAction( ScrAction::RecentScript, QPixmap(), QPixmap(), RecentScripts[m], QKeySequence(), this));
10729 cbradney 116
                connect( scrRecentScriptActions[strippedName], SIGNAL(triggeredData(QString)), this, SLOT(RecentScript(QString)) );
1718 craig 117
                menuMgr->addMenuItem(scrRecentScriptActions[strippedName], "RecentScripts");
1467 cbradney 118
        }
119
}
120
 
1718 craig 121
void ScripterCore::buildRecentScriptsMenu()
1467 cbradney 122
{
6852 tsoots 123
        RecentScripts = SavedRecentScripts;
1718 craig 124
        scrRecentScriptActions.clear();
125
        if (SavedRecentScripts.count() != 0)
1467 cbradney 126
        {
8562 jghali 127
                uint max = qMin(PrefsManager::instance()->appPrefs.RecentDCount, SavedRecentScripts.count());
1718 craig 128
                for (uint m = 0; m < max; ++m)
1467 cbradney 129
                {
1718 craig 130
                        QFileInfo fd(SavedRecentScripts[m]);
131
                        if (fd.exists())
132
                        {
133
                                QString strippedName=SavedRecentScripts[m];
134
                                strippedName.remove(QDir::separator());
9857 cbradney 135
                                scrRecentScriptActions.insert(strippedName, new ScrAction( ScrAction::RecentScript, QPixmap(), QPixmap(), SavedRecentScripts[m], QKeySequence(), this));
10729 cbradney 136
                                connect( scrRecentScriptActions[strippedName], SIGNAL(triggeredData(QString)), this, SLOT(RecentScript(QString)) );
1718 craig 137
                                menuMgr->addMenuItem(scrRecentScriptActions[strippedName], "RecentScripts");
138
                        }
1467 cbradney 139
                }
140
        }
141
}
142
 
143
void ScripterCore::FinishScriptRun()
144
{
5781 cbradney 145
        ScribusMainWindow* ScMW=ScCore->primaryMainWindow();
4026 craig 146
        if (ScMW->HaveDoc)
1467 cbradney 147
        {
4026 craig 148
                ScMW->propertiesPalette->setDoc(ScMW->doc);
5781 cbradney 149
                ScMW->layerPalette->setDoc(ScMW->doc);
4026 craig 150
                ScMW->outlinePalette->setDoc(ScMW->doc);
151
                ScMW->outlinePalette->BuildTree();
152
                ScMW->pagePalette->setView(ScMW->view);
153
                ScMW->pagePalette->Rebuild();
154
                ScMW->doc->RePos = true;
10039 fschmid 155
/*              QImage pgPix(10, 10, QImage::Format_ARGB32);
2712 fschmid 156
                QRect rd = QRect(0,0,9,9);
157
                ScPainter *painter = new ScPainter(&pgPix, pgPix.width(), pgPix.height());
9882 fschmid 158
                for (int azz=0; azz<ScMW->doc->Items->count(); ++azz)
2712 fschmid 159
                {
4026 craig 160
                        PageItem *ite = ScMW->doc->Items->at(azz);
2712 fschmid 161
                        if (ite->Groups.count() != 0)
4026 craig 162
                                ScMW->doc->GroupOnPage(ite);
2712 fschmid 163
                        else
4026 craig 164
                                ite->OwnPage = ScMW->doc->OnPage(ite);
3657 cbradney 165
                        ite->setRedrawBounding();
5362 avox 166
                        if ((ite->itemType() == PageItem::TextFrame) || (ite->itemType() == PageItem::PathText)) // && (!ite->Redrawn))
2712 fschmid 167
                        {
168
                                if (ite->itemType() == PageItem::PathText)
169
                                {
170
                                        ite->Frame = false;
4688 cbradney 171
                                        ite->updatePolyClip();
2712 fschmid 172
                                        ite->DrawObj(painter, rd);
173
                                }
174
                                else
175
                                {
7994 avox 176
                                        if ((ite->prevInChain() != 0) || (ite->nextInChain() != 0))
2712 fschmid 177
                                        {
178
                                                PageItem *nextItem = ite;
9785 avox 179
                                                while (nextItem->prevInChain() != 0)
180
                                                        nextItem = nextItem->prevInChain();
2712 fschmid 181
                                                ite = nextItem;
182
                                                ite->DrawObj(painter, rd);
183
                                        }
184
                                        else
185
                                                ite->DrawObj(painter, rd);
186
                                }
187
                        }
188
                }
10039 fschmid 189
                delete painter; */
4026 craig 190
                ScMW->doc->RePos = false;
4847 cbradney 191
                if (ScMW->doc->m_Selection->count() != 0)
2071 subik 192
                {
4847 cbradney 193
                        ScMW->doc->m_Selection->itemAt(0)->emitAllToGUI();
194
                        ScMW->HaveNewSel(ScMW->doc->m_Selection->itemAt(0)->itemType());
2071 subik 195
                }
1467 cbradney 196
                else
4026 craig 197
                        ScMW->HaveNewSel(-1);
198
                ScMW->view->DrawNew();
199
                //CB Really only need (want?) this for new docs, but we need it after a call to ScMW doFileNew.
3882 cbradney 200
                //We don't want it in cmddoc calls as itll interact with the GUI before a script may be finished.
4026 craig 201
                ScMW->HaveNewDoc();
1467 cbradney 202
        }
203
}
204
 
2622 craig 205
void ScripterCore::runScriptDialog()
1467 cbradney 206
{
207
        QString fileName;
10398 cbradney 208
        QString curDirPath = QDir::currentPath();
5781 cbradney 209
        RunScriptDialog dia( ScCore->primaryMainWindow(), m_enableExtPython );
2622 craig 210
        if (dia.exec())
1467 cbradney 211
        {
2622 craig 212
                fileName = dia.selectedFile();
213
                slotRunScriptFile(fileName, dia.extensionRequested());
1718 craig 214
 
10517 cbradney 215
                if (RecentScripts.indexOf(fileName) == -1)
1467 cbradney 216
                        RecentScripts.prepend(fileName);
217
                else
218
                {
10598 cbradney 219
                        RecentScripts.removeAll(fileName);
1467 cbradney 220
                        RecentScripts.prepend(fileName);
221
                }
1718 craig 222
                rebuildRecentScriptsMenu();
1467 cbradney 223
        }
2622 craig 224
        QDir::setCurrent(curDirPath);
1467 cbradney 225
        FinishScriptRun();
226
}
227
 
1718 craig 228
void ScripterCore::StdScript(QString basefilename)
1467 cbradney 229
{
1718 craig 230
        QString pfad = ScPaths::instance().scriptDir();
1467 cbradney 231
        QString pfad2;
232
        pfad2 = QDir::convertSeparators(pfad);
1718 craig 233
        QString fn = pfad2+basefilename+".py";
1467 cbradney 234
        QFileInfo fd(fn);
235
        if (!fd.exists())
236
                return;
237
        slotRunScriptFile(fn);
238
        FinishScriptRun();
239
}
240
 
1718 craig 241
void ScripterCore::RecentScript(QString fn)
1467 cbradney 242
{
243
        QFileInfo fd(fn);
244
        if (!fd.exists())
245
        {
10598 cbradney 246
                RecentScripts.removeAll(fn);
1718 craig 247
                rebuildRecentScriptsMenu();
1467 cbradney 248
                return;
249
        }
250
        slotRunScriptFile(fn);
251
        FinishScriptRun();
252
}
253
 
1752 craig 254
void ScripterCore::slotRunScriptFile(QString fileName, bool inMainInterpreter)
1467 cbradney 255
{
7980 fschmid 256
        PyThreadState *stateo = NULL;
257
        PyThreadState *state = NULL;
1467 cbradney 258
        QFileInfo fi(fileName);
10598 cbradney 259
        QByteArray na = fi.fileName().toLatin1();
1753 craig 260
        // Set up a sub-interpreter if needed:
261
        if (!inMainInterpreter)
262
        {
11633 jghali 263
                ScCore->primaryMainWindow()->propertiesPalette->unsetDoc();
264
                ScCore->primaryMainWindow()->pagePalette->setView(NULL);
5781 cbradney 265
                ScCore->primaryMainWindow()->ScriptRunning = true;
9380 fschmid 266
                qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
1753 craig 267
                // Create the sub-interpreter
268
                // FIXME: This calls abort() in a Python debug build. We're doing something wrong.
269
                stateo = PyEval_SaveThread();
270
                state = Py_NewInterpreter();
271
                // Chdir to the dir the script is in
10598 cbradney 272
                QDir::setCurrent(fi.absolutePath());
1753 craig 273
                // Init the scripter module in the sub-interpreter
5781 cbradney 274
                initscribus(ScCore->primaryMainWindow());
1753 craig 275
        }
276
        // Make sure sys.argv[0] is the path to the script
4863 craig 277
        char* comm[2];
1467 cbradney 278
        comm[0] = na.data();
2705 craig 279
        // and tell the script if it's running in the main intepreter or
280
        // a subinterpreter using the second argument, ie sys.argv[1]
281
        if (inMainInterpreter)
282
                comm[1] = const_cast<char*>("ext");
283
        else
284
                comm[1] = const_cast<char*>("sub");
285
        PySys_SetArgv(2, comm);
1718 craig 286
        // call python script
1467 cbradney 287
        PyObject* m = PyImport_AddModule((char*)"__main__");
288
        if (m == NULL)
289
                qDebug("Failed to get __main__ - aborting script");
290
        else
291
        {
292
                // FIXME: If filename contains chars outside 7bit ascii, might be problems
293
                PyObject* globals = PyModule_GetDict(m);
294
                // Build the Python code to run the script
8071 subik 295
                //QString cm = QString("from __future__ import division\n"); removed due #5252 PV
296
                QString cm = QString("import sys\n");
1753 craig 297
                cm        += QString("import cStringIO\n");
1467 cbradney 298
                /* Implementation of the help() in pydoc.py reads some OS variables
299
                 * for output settings. I use ugly hack to stop freezing calling help()
300
                 * in script. pv. */
1753 craig 301
                cm        += QString("import os\nos.environ['PAGER'] = '/bin/false'\n"); // HACK
10598 cbradney 302
                cm        += QString("sys.path[0] = \"%1\"\n").arg(fi.absolutePath());
1753 craig 303
                // Replace sys.stdin with a dummy StringIO that always returns
304
                // "" for read
305
                cm        += QString("sys.stdin = cStringIO.StringIO()\n");
306
                cm        += QString("try:\n");
307
                cm        += QString("    execfile(\"%1\")\n").arg(fileName);
308
                cm        += QString("except SystemExit:\n");
309
                cm        += QString("    pass\n");
1467 cbradney 310
                // Capture the text of any other exception that's raised by the interpreter
311
                // into a StringIO buffer for later extraction.
1753 craig 312
                cm        += QString("except:\n");
313
                cm        += QString("    import traceback\n");
314
                cm        += QString("    import scribus\n");                  // we stash our working vars here
315
                cm        += QString("    scribus._f=cStringIO.StringIO()\n");
316
                cm        += QString("    traceback.print_exc(file=scribus._f)\n");
317
                cm        += QString("    _errorMsg = scribus._f.getvalue()\n");
318
                cm        += QString("    del(scribus._f)\n");
319
                // We re-raise the exception so the return value of PyRun_StringFlags reflects
1467 cbradney 320
                // the fact that an exception has ocurred.
1753 craig 321
                cm        += QString("    raise\n");
1467 cbradney 322
                // FIXME: if cmd contains chars outside 7bit ascii, might be problems
10598 cbradney 323
                QByteArray cmd = cm.toLatin1();
1753 craig 324
                // Now run the script in the interpreter's global scope. It'll run in a
325
                // sub-interpreter if we created and switched to one earlier, otherwise
326
                // it'll run in the main interpreter.
1467 cbradney 327
                PyObject* result = PyRun_String(cmd.data(), Py_file_input, globals, globals);
328
                // NULL is returned if an exception is set. We don't care about any
329
                // other return value (most likely None anyway) and can ignore it.
330
                if (result == NULL)
331
                {
1753 craig 332
                        // We've already saved the exception text, so clear the exception
333
                        PyErr_Clear();
334
                        PyObject* errorMsgPyStr = PyMapping_GetItemString(globals, (char*)"_errorMsg");
1467 cbradney 335
                        if (errorMsgPyStr == NULL)
336
                        {
337
                                // It's rather unlikely that this will ever be reached - to get here
338
                                // we'd have to fail to retrive the string we just created.
339
                                qDebug("Error retrieving error message content after script exception!");
340
                                qDebug("Exception was:");
341
                                PyErr_Print();
342
                        }
343
                        else
344
                        {
345
                                QString errorMsg = PyString_AsString(errorMsgPyStr);
346
                                // Display a dialog to the user with the exception
347
                                QClipboard *cp = QApplication::clipboard();
348
                                cp->setText(errorMsg);
5243 cbradney 349
                                ScCore->closeSplash();
5781 cbradney 350
                                QMessageBox::warning(ScCore->primaryMainWindow(),
1467 cbradney 351
                                                                        tr("Script error"),
6520 subik 352
                                                                        "<qt><p>"
7123 fschmid 353
                                                                        + tr("If you are running an official script report it at <a href=\"http://bugs.scribus.net\">bugs.scribus.net</a> please.")
6520 subik 354
                                                                        + "</p><pre>" +errorMsg + "</pre><p>"
355
                                                                        + tr("This message is in your clipboard too. Use Ctrl+V to paste it into bug tracker.")
356
                                                                        + "</p></qt>");
1467 cbradney 357
                        }
358
                } // end if result == NULL
359
                // Because 'result' may be NULL, not a PyObject*, we must call PyXDECREF not Py_DECREF
360
                Py_XDECREF(result);
361
        } // end if m == NULL
1753 craig 362
        if (!inMainInterpreter)
363
        {
364
                Py_EndInterpreter(state);
365
                PyEval_RestoreThread(stateo);
9380 fschmid 366
//              qApp->restoreOverrideCursor();
1753 craig 367
        }
5781 cbradney 368
        ScCore->primaryMainWindow()->ScriptRunning = false;
1467 cbradney 369
}
370
 
5051 subik 371
void ScripterCore::slotRunScript(const QString Script)
1467 cbradney 372
{
11633 jghali 373
        ScCore->primaryMainWindow()->propertiesPalette->unsetDoc();
374
        ScCore->primaryMainWindow()->pagePalette->setView(NULL);
5781 cbradney 375
        ScCore->primaryMainWindow()->ScriptRunning = true;
5051 subik 376
        inValue = Script;
377
        QString cm;
378
        cm = "# -*- coding: utf8 -*- \n";
379
        if (PyThreadState_Get() != NULL)
1467 cbradney 380
        {
5781 cbradney 381
                initscribus(ScCore->primaryMainWindow());
2614 subik 382
                /* HACK: following loop handles all input line by line.
383
                It *should* use I.C. because of docstrings etc. I.I. cannot
384
                handle docstrings right.
385
                Calling all code in one command:
386
                ia = code.InteractiveInterpreter() ia.runsource(getval())
5051 subik 387
                works fine in plain Python. Not here. WTF? */
11899 subik 388
                cm += (
389
                                "try:\n"
390
                                "    import cStringIO\n"
391
                                "    scribus._bu = cStringIO.StringIO()\n"
392
                                "    sys.stdout = scribus._bu\n"
393
                                "    sys.stderr = scribus._bu\n"
394
                                "    sys.argv = ['scribus', 'ext']\n" // this is the PySys_SetArgv replacement
395
                                "    for i in scribus.getval().splitlines():\n"
396
                                "        scribus._ia.push(i)\n"
397
                                "    scribus.retval(scribus._bu.getvalue())\n"
398
                                "    sys.stdout = sys.__stdout__\n"
399
                                "    sys.stderr = sys.__stderr__\n"
400
                                "except SystemExit:\n"
401
                                "    print 'Catched SystemExit - it is not good for Scribus'\n"
402
                                "except KeyboardInterrupt:\n"
403
                                "    print 'Catched KeyboardInterrupt - it is not good for Scribus'\n"
404
                          );
1467 cbradney 405
        }
2706 craig 406
        // Set up sys.argv
5051 subik 407
        /* PV - WARNING: THIS IS EVIL! This code summons a crash - see
408
        bug #3510. I don't know why as the Python C API is a little
409
        bit magic for me. It looks like it replaces the cm QString or what...
410
        "In file tools/qgarray.cpp, line 147: Out of memory"
411
        Anyway - sys.argv is set above
2705 craig 412
        char* comm[1];
413
        comm[0] = const_cast<char*>("scribus");
414
        // the scripter console runs everything in the main interpreter
415
        // tell the code it's running there.
416
        comm[1] = const_cast<char*>("ext");
5051 subik 417
        PySys_SetArgv(2, comm); */
2706 craig 418
        // then run the code
419
        PyObject* m = PyImport_AddModule((char*)"__main__");
420
        if (m == NULL)
421
                qDebug("Failed to get __main__ - aborting script");
422
        else
423
        {
424
                PyObject* globals = PyModule_GetDict(m);
10493 fschmid 425
                PyObject* result = PyRun_String(cm.toUtf8().data(), Py_file_input, globals, globals);
2706 craig 426
                if (result == NULL)
427
                {
428
                        PyErr_Print();
5781 cbradney 429
                        QMessageBox::warning(ScCore->primaryMainWindow(), tr("Script error"),
2957 subik 430
                                        "<qt>" + tr("There was an internal error while trying the "
2706 craig 431
                                           "command you entered. Details were printed to "
2957 subik 432
                                           "stderr. ") + "</qt>");
2706 craig 433
                }
11899 subik 434
                else
435
                // Because 'result' may be NULL, not a PyObject*, we must call PyXDECREF not Py_DECREF
436
                        Py_XDECREF(result);
2706 craig 437
        }
5781 cbradney 438
        ScCore->primaryMainWindow()->ScriptRunning = false;
1467 cbradney 439
}
440
 
1718 craig 441
void ScripterCore::slotInteractiveScript(bool visible)
1467 cbradney 442
{
2600 cbradney 443
        QObject::disconnect( scrScripterActions["scripterShowConsole"], SIGNAL(toggled(bool)) , this, SLOT(slotInteractiveScript(bool)) );
2614 subik 444
 
10598 cbradney 445
        scrScripterActions["scripterShowConsole"]->setChecked(visible);
5243 cbradney 446
        pcon->setFonts();
2503 subik 447
        pcon->setShown(visible);
2614 subik 448
 
2600 cbradney 449
        QObject::connect( scrScripterActions["scripterShowConsole"], SIGNAL(toggled(bool)) , this, SLOT(slotInteractiveScript(bool)) );
1467 cbradney 450
}
451
 
452
void ScripterCore::slotExecute()
453
{
5051 subik 454
        slotRunScript(pcon->command());
455
        pcon->outputEdit->append(returnString);
2503 subik 456
        pcon->commandEdit->ensureCursorVisible();
1467 cbradney 457
        FinishScriptRun();
458
}
459
 
460
void ScripterCore::ReadPlugPrefs()
461
{
2856 cbradney 462
        PrefsContext* prefs = PrefsManager::instance()->prefsFile->getPluginContext("scriptplugin");
1750 craig 463
        if (!prefs)
1467 cbradney 464
        {
1750 craig 465
                qDebug("scriptplugin: Unable to load prefs");
1467 cbradney 466
                return;
467
        }
1750 craig 468
        PrefsTable* prefRecentScripts = prefs->getTable("recentscripts");
469
        if (!prefRecentScripts)
470
        {
471
                qDebug("scriptplugin: Unable to get recent scripts");
1467 cbradney 472
                return;
473
        }
1750 craig 474
        // Load recent scripts from the prefs
475
        for (int i = 0; i < prefRecentScripts->getRowCount(); i++)
476
                SavedRecentScripts.append(prefRecentScripts->get(i,0));
1752 craig 477
        // then get more general preferences
3216 craig 478
        m_enableExtPython = prefs->getBool("extensionscripts",false);
479
        m_importAllNames = prefs->getBool("importall",true);
480
        m_startupScript = prefs->get("startupscript", QString::null);
4101 craig 481
        // and have the console window set up its position
1467 cbradney 482
}
483
 
484
void ScripterCore::SavePlugPrefs()
485
{
2856 cbradney 486
        PrefsContext* prefs = PrefsManager::instance()->prefsFile->getPluginContext("scriptplugin");
1750 craig 487
        if (!prefs)
1467 cbradney 488
        {
1750 craig 489
                qDebug("scriptplugin: Unable to load prefs");
490
                return;
1467 cbradney 491
        }
1750 craig 492
        PrefsTable* prefRecentScripts = prefs->getTable("recentscripts");
493
        if (!prefRecentScripts)
494
        {
495
                qDebug("scriptplugin: Unable to get recent scripts");
1467 cbradney 496
                return;
1750 craig 497
        }
8585 cbradney 498
        for (int i = 0; i < RecentScripts.count(); i++)
1750 craig 499
                prefRecentScripts->set(i, 0, RecentScripts[i]);
1752 craig 500
        // then save more general preferences
3216 craig 501
        prefs->set("extensionscripts", m_enableExtPython);
502
        prefs->set("importall", m_importAllNames);
503
        prefs->set("startupscript", m_startupScript);
1467 cbradney 504
}
505
 
506
void ScripterCore::aboutScript()
507
{
6235 fschmid 508
        QString fname = ScCore->primaryMainWindow()->CFileDialog(".", tr("Examine Script"), tr("Python Scripts (*.py *.PY);;All Files (*)"), "", fdNone);
2503 subik 509
        if (fname == QString::null)
510
                return;
4458 subik 511
        QString html("<html><body>");
1467 cbradney 512
        QFileInfo fi = QFileInfo(fname);
513
        QFile input(fname);
8501 cbradney 514
        if(!input.open(QIODevice::ReadOnly))
1467 cbradney 515
                return;
10004 fschmid 516
        QTextStream intputstream(&input);
517
        QString content = intputstream.readAll();
1467 cbradney 518
        QString docstring = content.section("\"\"\"", 1, 1);
2877 cbradney 519
        if (!docstring.isEmpty())
1467 cbradney 520
        {
6260 fschmid 521
                html += QString("<h1>%1 %2</h1>").arg( tr("Documentation for:")).arg(fi.fileName());
4458 subik 522
                html += QString("<p>%1</p>").arg(docstring.replace("\n\n", "<br><br>"));
1467 cbradney 523
        }
524
        else
525
        {
6260 fschmid 526
                html += QString("<p><b>%1 %2 %3</b></p>").arg( tr("Script")).arg(fi.fileName()).arg( tr(" doesn't contain any docstring!"));
4458 subik 527
                html += QString("<pre>%4</pre>").arg(content);
1467 cbradney 528
        }
4458 subik 529
        html += "</body></html>";
1467 cbradney 530
        input.close();
4458 subik 531
        HelpBrowser *dia = new HelpBrowser(0, QObject::tr("About Script") + " " + fi.fileName(), "en");
532
        dia->setText(html);
1467 cbradney 533
        dia->show();
534
}
1752 craig 535
 
536
void ScripterCore::initExtensionScripts()
537
{
538
        // Nothing to do currently
539
}
540
 
541
void ScripterCore::runStartupScript()
542
{
8625 subik 543
        if ((m_enableExtPython) && (!m_startupScript.isNull()))
1752 craig 544
        {
3216 craig 545
                if (QFile::exists(this->m_startupScript))
1752 craig 546
                {
547
                        // run the script in the main interpreter. The user will be informed
548
                        // with a dialog if something has gone wrong.
3216 craig 549
                        this->slotRunScriptFile(this->m_startupScript, true);
1752 craig 550
                }
551
                else
10598 cbradney 552
                        qDebug("Startup script enabled, but couln't find script %s.", m_startupScript.toAscii().constData());
1752 craig 553
        }
554
}
555
 
2226 cbradney 556
void ScripterCore::languageChange()
2223 cbradney 557
{
10427 cbradney 558
        scrScripterActions["scripterExecuteScript"]->setText(QObject::tr("&Execute Script..."));
559
        scrScripterActions["scripterShowConsole"]->setText(QObject::tr("Show &Console"));
560
        scrScripterActions["scripterAboutScript"]->setText(QObject::tr("&About Script..."));
2503 subik 561
 
10427 cbradney 562
        menuMgr->setText("Scripter", QObject::tr("&Script"));
563
        menuMgr->setText("ScribusScripts", QObject::tr("&Scribus Scripts"));
564
        menuMgr->setText("RecentScripts", QObject::tr("&Recent Scripts"));
2223 cbradney 565
}
2706 craig 566
 
567
bool ScripterCore::setupMainInterpreter()
568
{
569
        QString cm = QString(
570
                "# -*- coding: utf-8 -*-\n"
571
                "import scribus\n"
572
                "import sys\n"
573
                "sys.path[0] = \"%1\"\n"
574
                "import cStringIO\n"
575
                "sys.stdin = cStringIO.StringIO()\n"
576
                "import code\n"
577
                "scribus._ia = code.InteractiveConsole(globals())\n"
578
                ).arg(ScPaths::instance().scriptDir());
3216 craig 579
        if (m_importAllNames)
2706 craig 580
                cm += "from scribus import *\n";
9535 fschmid 581
        QByteArray cmd = cm.toUtf8();
2706 craig 582
        if (PyRun_SimpleString(cmd.data()))
583
        {
584
                PyErr_Print();
5781 cbradney 585
                QMessageBox::warning(ScCore->primaryMainWindow(), tr("Script error"),
2706 craig 586
                                tr("Setting up the Python plugin failed. "
587
                                   "Error details were printed to stderr. "));
588
                return false;
589
        }
590
        else
591
                return true;
592
}
3216 craig 593
 
594
void ScripterCore::setStartupScript(const QString& newScript)
595
{
596
        m_startupScript = newScript;
597
}
598
 
599
void ScripterCore::setExtensionsEnabled(bool enable)
600
{
601
        m_enableExtPython = enable;
602
}
603
 
604
const QString & ScripterCore::startupScript() const
605
{
606
        return m_startupScript;
607
}
608
 
609
bool ScripterCore::extensionsEnabled() const
610
{
611
        return m_enableExtPython;
612
}