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 */
7 #include <QString>
8 #include <QDir>
9 #include <QMessageBox>
10 #include <QInputDialog>
11 #include <QtDebug>
12 #include <QApplication>
13 
14 #include "scripterimpl.h"
15 #include "ui/scmessagebox.h"
16 
17 
ScripterImpl()18 ScripterImpl::ScripterImpl() : QObject(QApplication::instance())
19 {
20 	setObjectName("Scripter");
21 	_instance = this;
22 	qDebug() << "ScripterImpl object created";
23 }
24 
25 
26 
~ScripterImpl()27 ScripterImpl::~ScripterImpl()
28 {
29 	qDebug() << "destructor";
30 	Q_ASSERT(python);
31 	delete python;
32 	//Q_ASSERT(collected);
33 	//delete collected;
34 	_instance = nullptr;
35 	qDebug() << "Scripter deleted";
36 };
37 
38 
39 
instance()40 ScripterImpl *ScripterImpl::instance()
41 {
42 	//return QApplication::instance()->findChild<ScripterImpl *>("Scripter");
43 	return _instance;
44 }
45 
46 
init()47 bool ScripterImpl::init()
48 {
49 	collected = new QObject(this);
50 	collected->setObjectName(QString("internal_garbage_collector"));
51 	new PreferencesAPI();
52 	new DialogsAPI();
53 	python = new Pythonize();
54 	Q_CHECK_PTR(python);
55 	path = ScPaths::instance().libDir() + "plugins/scripter/";
56 	//qRegisterMetaType< QList<QVariant*> >("QList<QVariant*>");
57 	QString init_py = path + "init_scripter.py";
58 	bool ok = runScript(init_py);
59 	return ok;
60 }
61 
62 
63 
runScript(const QString & filename)64 bool ScripterImpl::runScript(const QString & filename)
65 {
66 	qDebug()  <<  "Running" << filename;
67 	if (!python->runScript(filename.toLocal8Bit().data()))
68 	{
69 		qDebug()  << "Running" << filename << "failed";
70 		return false;
71 	}
72 	return true;
73 }
74 
75 
cleanup()76 bool ScripterImpl::cleanup()
77 {
78 	QString clean_py = path + "cleanup_scripter.py";
79 	return runScript(clean_py);
80 }
81 
82 
83 /**
84  * Scripter.fromVariant(variant)
85  * variant is a QVariant
86  * returns instance of QObject-subclass
87  *
88  * This is a helper method for PyQt
89  * Because PyQt cannot cast a variant to a QObject or QWidget
90  * I hope that will change some time.
91  */
fromVariant(const QVariant & v)92 QObject *ScripterImpl::fromVariant(const QVariant& v)
93 {
94 
95 	if (v.canConvert< QWidget* >())
96 	{
97 		QObject* obj = qvariant_cast< QWidget* >(v);
98 		return obj;
99 	}
100 	else if (v.canConvert< QObject* >())
101 	{
102 		QObject* obj = qvariant_cast< QObject* >(v);
103 		return obj;
104 	}
105 	else
106 		return 0;
107 }
108 
109 
110 /**
111  * Scripter.openDocument(filename)
112  * filename is a string
113  * returns opened active Document object
114  */
openDocument(const QString & filename)115 QObject *ScripterImpl::openDocument(const QString & filename)
116 {
117 	bool ret = ScCore->primaryMainWindow()->loadDoc(filename);
118 	if (!ret)
119 	{
120 		RAISE("Failed to open " + filename);
121 		return nullptr;
122 	}
123 	return activeDocument();
124 }
125 
126 
127 
128 /**
129  * Scripter.activeDocument
130  * Property
131  * returns a Document object if a document is open
132  */
activeDocument()133 QObject *ScripterImpl::activeDocument()
134 {
135 	if (ScCore->primaryMainWindow()->HaveDoc)
136 		return new DocumentAPI();
137 	else
138 		return nullptr;
139 }
140 
141 
142 /**
143  * Scripter.activeWindow
144  * Property
145  * returns a Window object if a window is open
146  */
activeWindow()147 QObject *ScripterImpl::activeWindow()
148 {
149 	if (ScCore->primaryMainWindow()->HaveDoc)
150 		return new WindowAPI();
151 	else
152 		return nullptr;
153 }
154 
155 /**
156  * Scripter.colors
157  * Property
158  * returns a color object
159  */
colors()160 QList<QVariant> ScripterImpl::colors()
161 {
162 	QList<QVariant> l;
163 
164 	ColorList names = PrefsManager::instance()->colorSet();
165 	ColorList::Iterator it;
166 	for (it = names.begin(); it != names.end(); ++it)
167 	{
168 		ScColor *value = &(names[it.key()]);
169 		ColorAPI *color = new ColorAPI(value, it.key());
170 		l.append(qVariantFromValue((QObject *)(color)));
171 	}
172 	return l;
173 }
174 
fontInfo()175 QList< QVariant > ScripterImpl::fontInfo()
176 {
177 	int cc2 = 0;
178 	SCFontsIterator it2(PrefsManager::instance()->appPrefs.fontPrefs.AvailFonts);
179 	for ( ; it2.hasNext() ; it2.next())
180 	{
181 		if (it2.current().usable())
182 			cc2++;
183 	}
184 	QList<QVariant> l;
185 	SCFontsIterator it(PrefsManager::instance()->appPrefs.fontPrefs.AvailFonts);
186 	int cc = 0;
187 	for ( ; it.hasNext() ; it.next())
188 	{
189 		if (it.current().usable())
190 		{
191 			l.append(it.currentKey());
192 			cc++;
193 		}
194 	}
195 	return l;
196 }
197 
xFontInfo()198 QList<QVariant> ScripterImpl::xFontInfo()
199 {
200 	QList<QVariant> l;
201 	SCFontsIterator it(PrefsManager::instance()->appPrefs.fontPrefs.AvailFonts);
202 	int cc = 0;
203 	QList<QVariant> row;
204 	for ( ; it.hasNext() ; it.next())
205 	{
206 		row.append(it.currentKey());
207 		row.append(it.current().family());
208 		row.append(it.current().psName());
209 		row.append(it.current().subset());
210 		row.append(it.current().embedPs());
211 		row.append(it.current().fontFilePath());
212 		l.append(row);
213 		cc++;
214 	}
215 	return l;
216 }
217 
218 /**
219  * Scripter.newDocument(topMargin, bottomMargin, leftMargin, rightMargin, pageWIdth, pageHeight, orientation, firstPageNr, pagesTypes, facingPages, firstPageOrger, numPages)
220  * topMargin is double
221  * bottomMargin is double
222  * leftMargin is double
223  * rightMargin is double
224  * pageWidth is double
225  * pageHeight is double
226  * orientation is int
227  * firstPageNr is int
228  * unit is int
229  * pagesType is int
230  * facingPages is int
231  * firstPageOrder is int
232  * numPages is int
233  * returns new a new active Document object
234  */
newDocument(double topMargin,double bottomMargin,double leftMargin,double rightMargin,double pageWidth,double pageHeight,int orientation,int firstPageNr,int unit,int pagesType,int facingPages,int firstPageOrder,int numPages)235 QObject *ScripterImpl::newDocument(
236     double topMargin, double bottomMargin,
237     double leftMargin, double rightMargin,
238     double pageWidth, double pageHeight,
239     int orientation, int firstPageNr, int unit, int pagesType,
240     int facingPages, int firstPageOrder, int numPages)
241 {
242 	if (numPages <= 0)
243 		numPages = 1;
244 	if (pagesType == 0)
245 	{
246 		facingPages = 0;
247 		firstPageOrder = 0;
248 	}
249 	else
250 		facingPages = 1;
251 	// checking the bounds
252 	if (pagesType < firstPageOrder)
253 	{
254 		RAISE("firstPageOrder is bigger than allowed.");
255 		return nullptr;
256 	}
257 	if (orientation == 1)
258 	{
259 		double x = pageWidth;
260 		pageWidth = pageHeight;
261 		pageHeight = x;
262 	}
263 	bool ret = ScCore->primaryMainWindow()->doFileNew(
264 	               pageWidth, pageHeight, topMargin, leftMargin,
265 	               rightMargin, bottomMargin,
266 	               // XXX: add later?
267 	               // autoframes. It's disabled in python
268 	               // columnDistance, numberCols, autoframes,
269 	               0, 1, false,
270 	               pagesType, unit, firstPageOrder,
271 	               orientation, firstPageNr, "Custom", true, numPages);
272 	if (!ret)
273 	{
274 		RAISE("Page creation failed");
275 		return nullptr;
276 	}
277 	ScCore->primaryMainWindow()->doc->setPageSetFirstPage(pagesType, firstPageOrder);
278 	return activeDocument();
279 }
280 
281 
282 
283 
284 /*
285  * slot which emits a signal for PyQt
286  * init_scripter.py waits for it to create the menu
287  */
addToMainWindowMenu(ScribusMainWindow * mainwin)288 void ScripterImpl::addToMainWindowMenu(ScribusMainWindow *mainwin)
289 {
290 	emit createMenu(mainwin);
291 }
292 
language()293 QString ScripterImpl::language()
294 {
295 	return ScCore->getGuiLanguage();
296 }
297 
298 
299 /*
300  * A simple test method: input some code and evaluate it
301  * It was used before there was a script editor and console
302  * I will keep it for now but will remove it later.
303  */
test()304 bool ScripterImpl::test()
305 {
306 	bool ok;
307 	QString code = QInputDialog::getText(
308 	                   0, tr("Scripter"), tr("Please enter a Python command:"), QLineEdit::Normal,
309 	                   "import scripterconsole; scripterconsole.show_console()", &ok);
310 	if (ok && !code.isEmpty())
311 	{
312 		bool success = python->runString(code.toUtf8().data());
313 		if (!success)
314 			qDebug() << "python->runString(..) failed";
315 	}
316 	return true;
317 }
318 
319 
320 
321 /**
322  * Scripter.aboutScripter()
323  *
324  * Like qApp.aboutQt()
325  * The quickest way to see if calling Scripter works.
326  */
aboutScripter()327 void ScripterImpl::aboutScripter()
328 {
329 	ScMessageBox::information(
330 	    0, //(QWidget*)doc->scMW(),
331 	    tr("Scribus - Scripter Plugin"),
332 	    tr("If you see this box, Scripter probably works :)"),
333 	    QMessageBox::Ok|QMessageBox::Default|QMessageBox::Escape,
334 	    QMessageBox::NoButton);
335 }
336 
337 
338 ScripterImpl *ScripterImpl::_instance;
339 
340 
341