Subversion Repositories Scribus

Rev

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