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 "cmdobj.h"
8 
9 #include "appmodes.h"
10 #include "cmdutil.h"
11 #include "commonstrings.h"
12 #include "pageitem_table.h"
13 #include "scribuscore.h"
14 #include "scribusdoc.h"
15 #include "scribusview.h"
16 #include "selection.h"
17 #include "util_math.h"
18 
19 
scribus_createrect(PyObject *,PyObject * args)20 PyObject *scribus_createrect(PyObject* /* self */, PyObject* args)
21 {
22 	double x, y, w, h;
23 	char *Name = const_cast<char*>("");
24 
25 	if (!PyArg_ParseTuple(args, "dddd|es", &x, &y, &w, &h, "utf-8", &Name))
26 		return nullptr;
27 	if (!checkHaveDocument())
28 		return nullptr;
29 //	if (ItemExists(QString::fromUtf8(Name)))
30 //	{
31 //		PyErr_SetString(NameExistsError, QObject::tr("An object with the requested name already exists.","python error"));
32 //		return nullptr;
33 //	}
34 	ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
35 	int i = doc->itemAdd(PageItem::Polygon, PageItem::Rectangle,
36 						pageUnitXToDocX(x), pageUnitYToDocY(y),
37 						ValueToPoint(w), ValueToPoint(h),
38 						doc->itemToolPrefs().shapeLineWidth,
39 						doc->itemToolPrefs().shapeFillColor, doc->itemToolPrefs().shapeLineColor);
40 //	ScCore->primaryMainWindow()->doc->setRedrawBounding(ScCore->primaryMainWindow()->doc->Items->at(i));
41 	if (strlen(Name) > 0)
42 	{
43 		QString objName = QString::fromUtf8(Name);
44 		if (!ItemExists(objName))
45 			doc->Items->at(i)->setItemName(objName);
46 	}
47 	return PyUnicode_FromString(doc->Items->at(i)->itemName().toUtf8());
48 }
49 
50 
scribus_createellipse(PyObject *,PyObject * args)51 PyObject *scribus_createellipse(PyObject* /* self */, PyObject* args)
52 {
53 	double x, y, w, h;
54 	char *Name = const_cast<char*>("");
55 	if (!PyArg_ParseTuple(args, "dddd|es", &x, &y, &w, &h, "utf-8", &Name))
56 		return nullptr;
57 	if (!checkHaveDocument())
58 		return nullptr;
59 	int i = ScCore->primaryMainWindow()->doc->itemAdd(PageItem::Polygon, PageItem::Ellipse,
60 										pageUnitXToDocX(x),
61 										pageUnitYToDocY(y),
62 										ValueToPoint(w),
63 										ValueToPoint(h),
64 										ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineWidth,
65 										ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeFillColor,
66 										ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineColor);
67 	if (strlen(Name) > 0)
68 	{
69 		QString objName = QString::fromUtf8(Name);
70 		if (!ItemExists(objName))
71 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
72 	}
73 	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
74 }
75 
76 
scribus_createimage(PyObject *,PyObject * args)77 PyObject *scribus_createimage(PyObject* /* self */, PyObject* args)
78 {
79 	double x, y, w, h;
80 	char *Name = const_cast<char*>("");
81 	if (!PyArg_ParseTuple(args, "dddd|es", &x, &y, &w, &h, "utf-8", &Name))
82 		return nullptr;
83 	if (!checkHaveDocument())
84 		return nullptr;
85 	int i = ScCore->primaryMainWindow()->doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified,
86 									pageUnitXToDocX(x),
87 									pageUnitYToDocY(y),
88 									ValueToPoint(w),
89 									ValueToPoint(h),
90 									1, ScCore->primaryMainWindow()->doc->itemToolPrefs().imageFillColor,
91 									ScCore->primaryMainWindow()->doc->itemToolPrefs().imageStrokeColor);
92 	if (strlen(Name) > 0)
93 	{
94 		QString objName = QString::fromUtf8(Name);
95 		if (!ItemExists(objName))
96 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
97 	}
98 	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
99 }
100 
101 
scribus_createtext(PyObject *,PyObject * args)102 PyObject *scribus_createtext(PyObject* /* self */, PyObject* args)
103 {
104 	double x, y, w, h;
105 	char *Name = const_cast<char*>("");
106 	if (!PyArg_ParseTuple(args, "dddd|es", &x, &y, &w, &h, "utf-8", &Name))
107 		return nullptr;
108 	if (!checkHaveDocument())
109 		return nullptr;
110 	int i = ScCore->primaryMainWindow()->doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified,
111 								pageUnitXToDocX(x),
112 								pageUnitYToDocY(y),
113 								ValueToPoint(w),
114 								ValueToPoint(h),
115 								ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineWidth, CommonStrings::None,
116 								ScCore->primaryMainWindow()->doc->itemToolPrefs().textColor);
117 	if (strlen(Name) > 0)
118 	{
119 		QString objName = QString::fromUtf8(Name);
120 		if (!ItemExists(objName))
121 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
122 	}
123 	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
124 }
125 
scribus_createtable(PyObject *,PyObject * args)126 PyObject *scribus_createtable(PyObject* /* self */, PyObject* args)
127 {
128 	double x, y, w, h;
129 	int numRows, numColumns;
130 	char *Name = const_cast<char*>("");
131 	if (!PyArg_ParseTuple(args, "ddddii|es", &x, &y, &w, &h, &numRows, &numColumns, "utf-8", &Name))
132 		return nullptr;
133 	if (!checkHaveDocument())
134 		return nullptr;
135 	if (numRows < 1 || numColumns < 1)
136 	{
137 		PyErr_SetString(PyExc_ValueError, QObject::tr("Both numRows and numColumns must be greater than 0.","python error").toLocal8Bit().constData());
138 		return nullptr;
139 	}
140 	int i = ScCore->primaryMainWindow()->doc->itemAdd(PageItem::Table, PageItem::Unspecified,
141 								pageUnitXToDocX(x),
142 								pageUnitYToDocY(y),
143 								ValueToPoint(w),
144 								ValueToPoint(h),
145 								0,                    // Unused.
146 								CommonStrings::None,  // Unused.
147 								CommonStrings::None); // Unused.
148 	PageItem_Table *table = ScCore->primaryMainWindow()->doc->Items->at(i)->asTable();
149 	table->insertRows(0, numRows - 1);
150 	table->insertColumns(0, numColumns - 1);
151 	table->adjustTableToFrame();
152 	table->adjustFrameToTable();
153 	if (strlen(Name) > 0)
154 	{
155 		QString objName = QString::fromUtf8(Name);
156 		if (!ItemExists(objName))
157 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
158 	}
159 	return PyUnicode_FromString(table->itemName().toUtf8());
160 }
161 
scribus_createline(PyObject *,PyObject * args)162 PyObject *scribus_createline(PyObject* /* self */, PyObject* args)
163 {
164 	double x, y, w, h;
165 	char *Name = const_cast<char*>("");
166 	if (!PyArg_ParseTuple(args, "dddd|es", &x, &y, &w, &h, "utf-8", &Name))
167 		return nullptr;
168 	if (!checkHaveDocument())
169 		return nullptr;
170 	x = pageUnitXToDocX(x);
171 	y = pageUnitYToDocY(y);
172 	w = pageUnitXToDocX(w);
173 	h = pageUnitYToDocY(h);
174 //	if (ItemExists(QString::fromUtf8(Name)))
175 //	{
176 //		PyErr_SetString(NameExistsError,
177 //						QObject::tr("An object with the requested name already exists.",
178 //									"python error"));
179 //		return nullptr;
180 //	}
181 	int i = ScCore->primaryMainWindow()->doc->itemAdd(PageItem::Line, PageItem::Unspecified,
182 							   x, y, w, h,
183 							   ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineWidth,
184 							   ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeFillColor,
185 							   ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineColor);
186 	PageItem *it = ScCore->primaryMainWindow()->doc->Items->at(i);
187 	it->setRotation(xy2Deg(w-x, h-y));
188 	it->setWidthHeight(sqrt(pow(x-w, 2.0) + pow(y-h, 2.0)), 1.0);
189 	it->Sizing = false;
190 	it->updateClip();
191 	it->setRedrawBounding();
192 //	ScCore->primaryMainWindow()->doc->setRedrawBounding(it);
193 /* WTF? maybe I'll examine who's author later. Or maybe I'll remove it later ;)
194 	it->PoLine.resize(4);
195 	it->PoLine.setPoint(0, 0, 0);
196 	it->PoLine.setPoint(1, 0, 0);
197 	it->PoLine.setPoint(2, w-x, h-y);
198 	it->PoLine.setPoint(3, w-x, h-y);
199 	FPoint np2 = getMinClipF(&it->PoLine);
200 	if (np2.x() < 0)
201 	{
202 		it->PoLine.translate(-np2.x(), 0);
203 		ScCore->primaryMainWindow()->view->MoveItem(np2.x(), 0, it);
204 	}
205 	if (np2.y() < 0)
206 	{
207 		it->PoLine.translate(0, -np2.y());
208 		ScCore->primaryMainWindow()->view->MoveItem(0, np2.y(), it);
209 	}
210 	ScCore->primaryMainWindow()->view->SizeItem(it->PoLine.widthHeight().x(),
211 						 it->PoLine.widthHeight().y(), i, false, false, false);
212 	ScCore->primaryMainWindow()->view->AdjustItemSize(it);*/
213 	if (strlen(Name) > 0)
214 	{
215 		QString objName = QString::fromUtf8(Name);
216 		if (!ItemExists(objName))
217 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
218 	}
219 	return PyUnicode_FromString(it->itemName().toUtf8());
220 }
221 
222 
scribus_createpolyline(PyObject *,PyObject * args)223 PyObject *scribus_createpolyline(PyObject* /* self */, PyObject* args)
224 {
225 	char *Name = const_cast<char*>("");
226 	PyObject *il;
227 	// FIXME: PyList_Check failing will cause the function to return nullptr w/o an exception. Separarate out the check.
228 	if ((!PyArg_ParseTuple(args, "O|es", &il, "utf-8", &Name)) || (!PyList_Check(il)))
229 		return nullptr;
230 	if (!checkHaveDocument())
231 		return nullptr;
232 	int len = PyList_Size(il);
233 	if (len < 4)
234 	{
235 		PyErr_SetString(PyExc_ValueError, QObject::tr("Point list must contain at least two points (four values).","python error").toLocal8Bit().constData());
236 		return nullptr;
237 	}
238 	if ((len % 2) != 0)
239 	{
240 		PyErr_SetString(PyExc_ValueError, QObject::tr("Point list must contain an even number of values.","python error").toLocal8Bit().constData());
241 		return nullptr;
242 	}
243 //	if (ItemExists(QString::fromUtf8(Name)))
244 //	{
245 //		PyErr_SetString(NameExistsError, QObject::tr("An object with the requested name already exists.","python error").toLocal8Bit().constData());
246 //		return nullptr;
247 //	}
248 	double x, y, w, h;
249 	int i = 0;
250 	x = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
251 	i++;
252 	y = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
253 	i++;
254 	int ic = ScCore->primaryMainWindow()->doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, x, y, 1, 1,	ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineWidth, ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeFillColor, ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineColor);
255 	PageItem *it = ScCore->primaryMainWindow()->doc->Items->at(ic);
256 	it->PoLine.resize(2);
257 	it->PoLine.setPoint(0, 0, 0);
258 	it->PoLine.setPoint(1, 0, 0);
259 	int pp = 6;
260 	for (i = 2; i < len - 2; i += 2)
261 	{
262 		w = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
263 		h = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i+1))));
264 		it->PoLine.resize(pp);
265 		it->PoLine.setPoint(pp-4, w-x, h-y);
266 		it->PoLine.setPoint(pp-3, w-x, h-y);
267 		it->PoLine.setPoint(pp-2, w-x, h-y);
268 		it->PoLine.setPoint(pp-1, w-x, h-y);
269 		pp += 4;
270 	}
271 	pp -= 2;
272 	w = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, len-2))));
273 	h = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, len-1))));
274 	it->PoLine.resize(pp);
275 	it->PoLine.setPoint(pp-2, w-x, h-y);
276 	it->PoLine.setPoint(pp-1, w-x, h-y);
277 	FPoint np2 = getMinClipF(&it->PoLine);
278 	if (np2.x() < 0)
279 	{
280 		it->PoLine.translate(-np2.x(), 0);
281 		ScCore->primaryMainWindow()->doc->moveItem(np2.x(), 0, it);
282 	}
283 	if (np2.y() < 0)
284 	{
285 		it->PoLine.translate(0, -np2.y());
286 		ScCore->primaryMainWindow()->doc->moveItem(0, np2.y(), it);
287 	}
288 	ScCore->primaryMainWindow()->doc->sizeItem(it->PoLine.widthHeight().x(), it->PoLine.widthHeight().y(), it, false, false, false);
289 	ScCore->primaryMainWindow()->doc->adjustItemSize(it);
290 	if (strlen(Name) > 0)
291 	{
292 		QString objName = QString::fromUtf8(Name);
293 		if (!ItemExists(objName))
294 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
295 	}
296 	return PyUnicode_FromString(it->itemName().toUtf8());
297 }
298 
299 
scribus_createpolygon(PyObject *,PyObject * args)300 PyObject *scribus_createpolygon(PyObject* /* self */, PyObject* args)
301 {
302 	char *Name = const_cast<char*>("");
303 	PyObject *il;
304 	// FIXME: PyList_Check failing will cause the function to return nullptr w/o an exception. Separarate out the check.
305 	if ((!PyArg_ParseTuple(args, "O|es", &il, "utf-8", &Name)) || (!PyList_Check(il)))
306 		return nullptr;
307 	if (!checkHaveDocument())
308 		return nullptr;
309 	int len = PyList_Size(il);
310 	if (len < 6)
311 	{
312 		PyErr_SetString(PyExc_ValueError, QObject::tr("Point list must contain at least three points (six values).","python error").toLocal8Bit().constData());
313 		return nullptr;
314 	}
315 	if ((len % 2) != 0)
316 	{
317 		PyErr_SetString(PyExc_ValueError, QObject::tr("Point list must contain an even number of values.","python error").toLocal8Bit().constData());
318 		return nullptr;
319 	}
320 //	if (ItemExists(QString::fromUtf8(Name)))
321 //	{
322 //		PyErr_SetString(NameExistsError, QObject::tr("An object with the requested name already exists.","python error").toLocal8Bit().constData());
323 //		return nullptr;
324 //	}
325 	double x, y, w, h;
326 	int i = 0;
327 	x = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
328 	i++;
329 	y = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
330 	i++;
331 	int ic = ScCore->primaryMainWindow()->doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, x, y, 1, 1,	ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineWidth, ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeFillColor, ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineColor);
332 	PageItem *it = ScCore->primaryMainWindow()->doc->Items->at(ic);
333 	it->PoLine.resize(2);
334 	it->PoLine.setPoint(0, 0, 0);
335 	it->PoLine.setPoint(1, 0, 0);
336 	int pp = 6;
337 	for (i = 2; i < len - 2; i += 2)
338 	{
339 		w = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
340 		h = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i+1))));
341 		it->PoLine.resize(pp);
342 		it->PoLine.setPoint(pp-4, w-x, h-y);
343 		it->PoLine.setPoint(pp-3, w-x, h-y);
344 		it->PoLine.setPoint(pp-2, w-x, h-y);
345 		it->PoLine.setPoint(pp-1, w-x, h-y);
346 		pp += 4;
347 	}
348 	w = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, len-2))));
349 	h = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, len-1))));
350 	it->PoLine.resize(pp);
351 	it->PoLine.setPoint(pp-4, w-x, h-y);
352 	it->PoLine.setPoint(pp-3, w-x, h-y);
353 	it->PoLine.setPoint(pp-2, w-x, h-y);
354 	it->PoLine.setPoint(pp-1, w-x, h-y);
355 	pp += 2;
356 	it->PoLine.resize(pp);
357 	it->PoLine.setPoint(pp-2, 0, 0);
358 	it->PoLine.setPoint(pp-1, 0, 0);
359 	FPoint np2 = getMinClipF(&it->PoLine);
360 	if (np2.x() < 0)
361 	{
362 		it->PoLine.translate(-np2.x(), 0);
363 		ScCore->primaryMainWindow()->doc->moveItem(np2.x(), 0, it);
364 	}
365 	if (np2.y() < 0)
366 	{
367 		it->PoLine.translate(0, -np2.y());
368 		ScCore->primaryMainWindow()->doc->moveItem(0, np2.y(), it);
369 	}
370 	ScCore->primaryMainWindow()->doc->sizeItem(it->PoLine.widthHeight().x(), it->PoLine.widthHeight().y(), it, false, false, false);
371 	ScCore->primaryMainWindow()->doc->adjustItemSize(it);
372 	if (strlen(Name) > 0)
373 	{
374 		QString objName = QString::fromUtf8(Name);
375 		if (!ItemExists(objName))
376 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
377 	}
378 	return PyUnicode_FromString(it->itemName().toUtf8());
379 }
380 
scribus_createbezierline(PyObject *,PyObject * args)381 PyObject *scribus_createbezierline(PyObject* /* self */, PyObject* args)
382 {
383 	char *Name = const_cast<char*>("");
384 	PyObject *il;
385 	// FIXME: PyList_Check failing will cause the function to return nullptr w/o an exception. Separarate out the check.
386 	if ((!PyArg_ParseTuple(args, "O|es", &il, "utf-8", &Name)) || (!PyList_Check(il)))
387 		return nullptr;
388 	if (!checkHaveDocument())
389 		return nullptr;
390 	int len = PyList_Size(il);
391 	if (len < 8)
392 	{
393 		PyErr_SetString(PyExc_ValueError, QObject::tr("Point list must contain at least four points (eight values).","python error").toLocal8Bit().constData());
394 		return nullptr;
395 	}
396 	if ((len % 6) != 0)
397 	{
398 		PyErr_SetString(PyExc_ValueError, QObject::tr("Point list must have a multiple of six values.","python error").toLocal8Bit().constData());
399 		return nullptr;
400 	}
401 //	if (ItemExists(QString::fromUtf8(Name)))
402 //	{
403 //		PyErr_SetString(NameExistsError, QObject::tr("An object with the requested name already exists.","python error").toLocal8Bit().constData());
404 //		return nullptr;
405 //	}
406 	double x, y, w, h, kx, ky, kx2, ky2;
407 	int i = 0;
408 	x = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
409 	i++;
410 	y = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
411 	i++;
412 	kx = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
413 	i++;
414 	ky = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
415 	i++;
416 	kx2 = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
417 	i++;
418 	ky2 = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
419 	i++;
420 	//int ic = ScCore->primaryMainWindow()->view->PaintPolyLine(x, y, 1, 1,	ScCore->primaryMainWindow()->doc->toolSettings.dWidth, ScCore->primaryMainWindow()->doc->toolSettings.dBrush, ScCore->primaryMainWindow()->doc->toolSettings.dPen);
421 	int ic = ScCore->primaryMainWindow()->doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, x, y, 1, 1,	ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineWidth, ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeFillColor, ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineColor);
422 	PageItem *it = ScCore->primaryMainWindow()->doc->Items->at(ic);
423 	it->PoLine.resize(2);
424 	it->PoLine.setPoint(0, 0, 0);
425 	it->PoLine.setPoint(1, kx-x, ky-y);
426 	int pp = 6;
427 	for (i = 6; i < len - 6; i += 6)
428 	{
429 		w = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i))));
430 		h = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i+1))));
431 		kx = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i+2))));
432 		ky = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i+3))));
433 		kx2 = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i+4))));
434 		ky2 = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, i+5))));
435 		it->PoLine.resize(pp);
436 		it->PoLine.setPoint(pp-4, w-x, h-y);
437 		it->PoLine.setPoint(pp-3, kx-x, ky-y);
438 		it->PoLine.setPoint(pp-2, it->PoLine.point(pp-4));
439 		it->PoLine.setPoint(pp-1, kx2-x, ky2-y);
440 		pp += 4;
441 	}
442 	pp -= 2;
443 	w = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, len-6))));
444 	h = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, len-5))));
445 	kx = pageUnitXToDocX(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, len-4))));
446 	ky = pageUnitYToDocY(static_cast<double>(PyFloat_AsDouble(PyList_GetItem(il, len-3))));
447 	it->PoLine.resize(pp);
448 	it->PoLine.setPoint(pp-2, w-x, h-y);
449 	it->PoLine.setPoint(pp-1, kx-x, ky-y);
450 	FPoint np2 = getMinClipF(&it->PoLine);
451 	if (np2.x() < 0)
452 	{
453 		it->PoLine.translate(-np2.x(), 0);
454 		ScCore->primaryMainWindow()->doc->moveItem(np2.x(), 0, it);
455 	}
456 	if (np2.y() < 0)
457 	{
458 		it->PoLine.translate(0, -np2.y());
459 		ScCore->primaryMainWindow()->doc->moveItem(0, np2.y(), it);
460 	}
461 	ScCore->primaryMainWindow()->doc->sizeItem(it->PoLine.widthHeight().x(), it->PoLine.widthHeight().y(), it, false, false, false);
462 	ScCore->primaryMainWindow()->doc->adjustItemSize(it);
463 	if (strlen(Name) > 0)
464 	{
465 		QString objName = QString::fromUtf8(Name);
466 		if (!ItemExists(objName))
467 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
468 	}
469 	return PyUnicode_FromString(it->itemName().toUtf8());
470 }
471 
472 
473 /* 03/31/2004 - xception handling
474  */
scribus_createpathtext(PyObject *,PyObject * args)475 PyObject *scribus_createpathtext(PyObject* /* self */, PyObject* args)
476 {
477 	double x, y;
478 	char *Name = const_cast<char*>("");
479 	char *TextB = const_cast<char*>("");
480 	char *PolyB = const_cast<char*>("");
481 	if (!PyArg_ParseTuple(args, "ddeses|es", &x, &y, "utf-8", &TextB, "utf-8", &PolyB, "utf-8", &Name))
482 		return nullptr;
483 	if (!checkHaveDocument())
484 		return nullptr;
485 //	if (ItemExists(QString::fromUtf8(Name)))
486 //	{
487 //		PyErr_SetString(NameExistsError, QObject::tr("An object with the requested name already exists.","python error"));
488 //		return nullptr;
489 //	}
490 	//FIXME: Why use GetItem not GetUniqueItem? Maybe use GetUniqueItem and use the exceptions
491 	// its sets for us?
492 	PageItem *i = GetItem(QString::fromUtf8(TextB));
493 	PageItem *ii = GetItem(QString::fromUtf8(PolyB));
494 	if ((i == nullptr) || (ii == nullptr))
495 	{
496 		PyErr_SetString(NotFoundError, QObject::tr("Object not found.","python error").toLocal8Bit().constData());
497 		return nullptr;
498 	}
499 	ScCore->primaryMainWindow()->doc->m_Selection->clear();
500 	ScCore->primaryMainWindow()->doc->m_Selection->addItem(i);
501 	ScCore->primaryMainWindow()->doc->m_Selection->addItem(ii);
502 	ScCore->primaryMainWindow()->view->ToPathText();
503 	ScCore->primaryMainWindow()->doc->moveItem(pageUnitXToDocX(x) - i->xPos(), pageUnitYToDocY(y) - i->yPos(), i);
504 	if (strlen(Name) > 0)
505 	{
506 		QString objName = QString::fromUtf8(Name);
507 		if (!ItemExists(objName))
508 			i->setItemName(objName);
509 	}
510 	return PyUnicode_FromString(i->itemName().toUtf8());
511 }
512 
513 
514 /* 03/21/2004 - exception raised when Name doesn't exists. Doesn't crash then. (subik)
515  */
scribus_deleteobject(PyObject *,PyObject * args)516 PyObject *scribus_deleteobject(PyObject* /* self */, PyObject* args)
517 {
518 	char *Name = const_cast<char*>("");
519 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
520 		return nullptr;
521 	if (!checkHaveDocument())
522 		return nullptr;
523 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
524 	if (i == nullptr)
525 		return nullptr;
526 	ScCore->primaryMainWindow()->doc->m_Selection->clear();
527 	ScCore->primaryMainWindow()->doc->m_Selection->addItem(i);
528 	ScCore->primaryMainWindow()->doc->itemSelection_DeleteItem();
529 
530 	Py_RETURN_NONE;
531 }
532 
scribus_gettextflowmode(PyObject *,PyObject * args)533 PyObject *scribus_gettextflowmode(PyObject* /* self */, PyObject* args)
534 {
535 	char *name = const_cast<char*>("");
536 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &name))
537 		return NULL;
538 	if (!checkHaveDocument())
539 		return NULL;
540 	PageItem *item = GetUniqueItem(QString::fromUtf8(name));
541 	if (item == NULL)
542 		return NULL;
543 
544 	return PyLong_FromLong(static_cast<int>(item->textFlowMode()));
545 };
546 
547 /* 03/21/2004 - exception raises by non existent name (subik)
548  */
scribus_settextflowmode(PyObject *,PyObject * args)549 PyObject *scribus_settextflowmode(PyObject* /* self */, PyObject* args)
550 {
551 	char *name = const_cast<char*>("");
552 	int state = -1;
553 
554 	if (!PyArg_ParseTuple(args, "es|i", "utf-8", &name, &state))
555 		return nullptr;
556 	if (!checkHaveDocument())
557 		return nullptr;
558 	PageItem *i = GetUniqueItem(QString::fromUtf8(name));
559 	if (i == nullptr)
560 		return nullptr;
561 	if (state == -1)
562 	{
563 		if (i->textFlowAroundObject())
564 			i->setTextFlowMode(PageItem::TextFlowDisabled);
565 		else
566 			i->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
567 	}
568 	else if (state == (int) PageItem::TextFlowDisabled )
569 		i->setTextFlowMode(PageItem::TextFlowDisabled);
570 	else if (state == (int) PageItem::TextFlowUsesFrameShape )
571 		i->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
572 	else if (state == (int) PageItem::TextFlowUsesBoundingBox )
573 		i->setTextFlowMode(PageItem::TextFlowUsesBoundingBox);
574 	else if (state == (int) PageItem::TextFlowUsesContourLine )
575 		i->setTextFlowMode(PageItem::TextFlowUsesContourLine);
576 	ScCore->primaryMainWindow()->view->DrawNew();
577 	ScCore->primaryMainWindow()->slotDocCh(true);
578 
579 	Py_RETURN_NONE;
580 }
581 
582 
scribus_objectexists(PyObject *,PyObject * args)583 PyObject *scribus_objectexists(PyObject* /* self */, PyObject* args)
584 {
585 	char* name = const_cast<char*>("");
586 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &name))
587 		return nullptr;
588 	if (!checkHaveDocument())
589 		return nullptr;
590 	if (ItemExists(QString::fromUtf8(name)))
591 		return PyBool_FromLong(static_cast<long>(true));
592 	return PyBool_FromLong(static_cast<long>(false));
593 }
594 
scribus_getcharacterstyle(PyObject *,PyObject * args)595 PyObject *scribus_getcharacterstyle(PyObject* /* self */, PyObject* args)
596 {
597 	char *name = const_cast<char*>("");
598 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &name))
599 		return NULL;
600 	if (!checkHaveDocument())
601 		return NULL;
602 	PageItem *item = GetUniqueItem(QString::fromUtf8(name));
603 	if (item == NULL)
604 		return NULL;
605 	if ((item->itemType() != PageItem::TextFrame) && (item->itemType() != PageItem::PathText))
606 	{
607 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get character style of a non-text frame.", "python error").toLocal8Bit().constData());
608 		return NULL;
609 	}
610 
611 	ScribusDoc* currentDoc = ScCore->primaryMainWindow()->doc;
612 	StoryText&  itemText = item->itemText;
613 
614 	int selectionLength = itemText.selectionLength();
615 	if ((selectionLength > 0) || (currentDoc->appMode == modeEdit))
616 	{
617 		int cursorPos = (selectionLength > 0) ? itemText.startOfSelection() : itemText.cursorPosition();
618 		const CharStyle& currentStyle = itemText.charStyle(cursorPos);
619 		if (currentStyle.hasParent())
620 			return PyUnicode_FromString(currentStyle.parentStyle()->name().toUtf8());
621 	}
622 	else
623 	{
624 		const CharStyle& itemDefaultStyle = itemText.defaultStyle().charStyle();
625 		if (itemDefaultStyle.hasParent())
626 			return PyUnicode_FromString(itemDefaultStyle.parentStyle()->name().toUtf8());
627 	}
628 	Py_RETURN_NONE;
629 };
630 
631 /*
632  * Vaclav Smilauer, 2017-21-21
633  * Return style name of the object (or currently selected object)
634  */
scribus_getparagraphstyle(PyObject *,PyObject * args)635 PyObject *scribus_getparagraphstyle(PyObject* /* self */, PyObject* args)
636 {
637 	char *name = const_cast<char*>("");
638 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &name))
639 		return NULL;
640 	if (!checkHaveDocument())
641 		return NULL;
642 	PageItem *item = GetUniqueItem(QString::fromUtf8(name));
643 	if (item == NULL)
644 		return NULL;
645 	if ((item->itemType() != PageItem::TextFrame) && (item->itemType() != PageItem::PathText))
646 	{
647 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get style of a non-text frame.", "python error").toLocal8Bit().constData());
648 		return NULL;
649 	}
650 
651 	ScribusDoc* currentDoc = ScCore->primaryMainWindow()->doc;
652 	StoryText&  itemText = item->itemText;
653 
654 	int selectionLength = itemText.selectionLength();
655 	if ((selectionLength > 0) || (currentDoc->appMode == modeEdit))
656 	{
657 		int cursorPos = (selectionLength > 0) ? itemText.startOfSelection() : itemText.cursorPosition();
658 		const ParagraphStyle& currentStyle = itemText.paragraphStyle(cursorPos);
659 		if (currentStyle.hasParent())
660 			return PyUnicode_FromString(currentStyle.parentStyle()->name().toUtf8());
661 	}
662 	else
663 	{
664 		const ParagraphStyle& itemDefaultStyle = item->itemText.defaultStyle();
665 		if (itemDefaultStyle.hasParent())
666 			return PyUnicode_FromString(itemDefaultStyle.parentStyle()->name().toUtf8());
667 	}
668 	Py_RETURN_NONE;
669 };
670 
671 
672 
673 /*
674  * Craig Ringer, 2004-09-09
675  * Apply the named style to the currently selected object.
676  * pv, 2004-09-13, optionaly param objectName + "check the page" stuff
677  */
scribus_setparagraphstyle(PyObject *,PyObject * args)678 PyObject *scribus_setparagraphstyle(PyObject* /* self */, PyObject* args)
679 {
680 	char *style = const_cast<char*>("");
681 	char *name = const_cast<char*>("");
682 	if (!PyArg_ParseTuple(args, "es|es", "utf-8", &style, "utf-8", &name))
683 		return nullptr;
684 	if (!checkHaveDocument())
685 		return nullptr;
686 	PageItem *item = GetUniqueItem(QString::fromUtf8(name));
687 	if (item == nullptr)
688 		return nullptr;
689 	if ((item->itemType() != PageItem::TextFrame) && (item->itemType() != PageItem::PathText))
690 	{
691 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set style on a non-text frame.", "python error").toLocal8Bit().constData());
692 		return nullptr;
693 	}
694 
695 	ScribusDoc*  currentDoc = ScCore->primaryMainWindow()->doc;
696 	ScribusView* currentView = ScCore->primaryMainWindow()->view;
697 	ScribusMainWindow* currentWin = ScCore->primaryMainWindow();
698 
699 	// First, check if style name provided by user is available in document
700 	QString paraStyleName = QString::fromUtf8(style);
701 	if (!currentDoc->paragraphStyles().contains(paraStyleName))
702 	{
703 		// whoops, the user specified an invalid style, complain loudly.
704 		// FIXME: Should use a more specific exception.
705 		PyErr_SetString(NotFoundError, QObject::tr("Style not found.","python error").toLocal8Bit().constData());
706 		return nullptr;
707 	}
708 
709 	// For multiple selections or if current item has no text selected, we apply style in normal mode
710 	if (currentDoc->m_Selection->isMultipleSelection() || (item->itemText.selectionLength() <= 0))
711 	{
712 		if (currentDoc->m_Selection->count() <= 1)
713 		{
714 			currentView->deselectItems(true);
715 			currentView->selectItem(item, false);
716 		}
717 		int mode = currentDoc->appMode;
718 		currentDoc->appMode = modeNormal;
719 		currentDoc->itemSelection_SetNamedParagraphStyle(paraStyleName);
720 		currentDoc->appMode = mode;
721 		Py_RETURN_NONE;
722 	}
723 
724 	// For single items which have a text selection, we apply style in edit mode
725 	// Store text selection as clearing object selection
726 	// will also clear text selection
727 	int selectionStart =  item->itemText.startOfSelection();
728 	int selectionLength = item->itemText.selectionLength();
729 	// Quick hack to always apply on the right frame - pv
730 	currentView->deselectItems(true);
731 	//CB I dont think we need to draw here. Its faster if we dont.
732 	currentView->selectItem(item, false);
733 	// Restore text selection if necessary
734 	if (selectionStart >= 0)
735 	{
736 		item->itemText.deselectAll();
737 		item->itemText.select(selectionStart, selectionLength);
738 		item->HasSel = true;
739 	}
740 	// Now apply the style.
741 	int mode = currentDoc->appMode;
742 	currentDoc->appMode = modeEdit;
743 	currentWin->setNewParStyle(paraStyleName);
744 	currentDoc->appMode = mode;
745 
746 	Py_RETURN_NONE;
747 }
748 
749 /*
750 * Jean Ghali, 2017-07-18
751 * Apply the named character style to the currently selected object.
752 * pv, 2004-09-13, optionaly param objectName + "check the page" stuff
753 */
scribus_setcharstyle(PyObject *,PyObject * args)754 PyObject *scribus_setcharstyle(PyObject* /* self */, PyObject* args)
755 {
756 	char *style = const_cast<char*>("");
757 	char *name = const_cast<char*>("");
758 	if (!PyArg_ParseTuple(args, "es|es", "utf-8", &style, "utf-8", &name))
759 		return nullptr;
760 	if (!checkHaveDocument())
761 		return nullptr;
762 	PageItem *item = GetUniqueItem(QString::fromUtf8(name));
763 	if (item == nullptr)
764 		return nullptr;
765 	if ((item->itemType() != PageItem::TextFrame) && (item->itemType() != PageItem::PathText))
766 	{
767 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set character style on a non-text frame.", "python error").toLocal8Bit().constData());
768 		return nullptr;
769 	}
770 
771 	ScribusDoc*  currentDoc = ScCore->primaryMainWindow()->doc;
772 	ScribusView* currentView = ScCore->primaryMainWindow()->view;
773 	ScribusMainWindow* currentWin = ScCore->primaryMainWindow();
774 
775 	// First, check if style name provided by user is available in document
776 	QString charStyleName = QString::fromUtf8(style);
777 	if (!currentDoc->charStyles().contains(charStyleName))
778 	{
779 		// whoops, the user specified an invalid style, complain loudly.
780 		// FIXME: Should use a more specific exception.
781 		PyErr_SetString(NotFoundError, QObject::tr("Character style not found.", "python error").toLocal8Bit().constData());
782 		return nullptr;
783 	}
784 
785 	// For multiple selections or if current item has no text selected, we apply style in normal mode
786 	if (currentDoc->m_Selection->isMultipleSelection() || (item->itemText.selectionLength() <= 0))
787 	{
788 		if (currentDoc->m_Selection->count() <= 1)
789 		{
790 			currentView->deselectItems(true);
791 			currentView->selectItem(item, false);
792 		}
793 		int mode = currentDoc->appMode;
794 		currentDoc->appMode = modeNormal;
795 		currentDoc->itemSelection_SetNamedCharStyle(charStyleName);
796 		currentDoc->appMode = mode;
797 		Py_RETURN_NONE;
798 	}
799 
800 	// For single items which have a text selection, we apply style in edit mode
801 	// Store text selection as clearing object selection
802 	// will also clear text selection
803 	int selectionStart =  item->itemText.startOfSelection();
804 	int selectionLength = item->itemText.selectionLength();
805 
806 	// Quick hack to always apply on the right frame - pv
807 	currentView->deselectItems(true);
808 	//CB I dont think we need to draw here. Its faster if we dont.
809 	currentView->selectItem(item, false);
810 	// Restore text selection if necessary
811 	if (selectionStart >= 0)
812 	{
813 		item->itemText.deselectAll();
814 		item->itemText.select(selectionStart, selectionLength);
815 		item->HasSel = true;
816 	}
817 	// Now apply the style.
818 	int mode = ScCore->primaryMainWindow()->doc->appMode;
819 	currentDoc->appMode = modeEdit;
820 	currentWin->setNewCharStyle(charStyleName);
821 	currentDoc->appMode = mode;
822 
823 	Py_RETURN_NONE;
824 }
825 
scribus_duplicateobject(PyObject *,PyObject * args)826 PyObject *scribus_duplicateobject(PyObject * /* self */, PyObject *args)
827 {
828 	char* name = const_cast<char*>("");
829 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &name))
830 		return nullptr;
831 	if (!checkHaveDocument())
832 		return nullptr;
833 
834 	// Is there a special name given? Yes -> add this to selection
835 	ScribusMainWindow* currentWin = ScCore->primaryMainWindow();
836 	ScribusDoc* currentDoc = currentWin->doc;
837 
838 	PageItem *item = GetUniqueItem(QString::fromUtf8(name));
839 	if (item == nullptr)
840 		return nullptr;
841 	currentDoc->m_Selection->clear();
842 	currentDoc->m_Selection->addItem(item);
843 
844 	// do the duplicate
845 	currentDoc->itemSelection_Duplicate(0.0, 0.0);
846 
847 	return PyUnicode_FromString(currentDoc->m_Selection->itemAt(0)->itemName().toUtf8());
848 }
849 
scribus_duplicateobjects(PyObject *,PyObject * args)850 PyObject *scribus_duplicateobjects(PyObject * /* self */, PyObject *args)
851 {
852 	PyObject* pyObject = nullptr;
853 	if (!PyArg_ParseTuple(args, "|O", &pyObject))
854 		return nullptr;
855 	if (!checkHaveDocument())
856 		return nullptr;
857 
858 	// Is there a special name given? Yes -> add this to selection
859 	ScribusMainWindow* currentWin = ScCore->primaryMainWindow();
860 	ScribusDoc* currentDoc = currentWin->doc;
861 
862 	if ((pyObject != nullptr) && !PyUnicode_Check(pyObject) && !PyList_Check(pyObject))
863 	{
864 		PyErr_SetString(PyExc_TypeError, QObject::tr("incorrect argument: must be a string or a list of strings", "python error").toLocal8Bit().constData());
865 		return nullptr;
866 	}
867 
868 	QStringList itemNames;
869 	if ((pyObject != nullptr) && PyUnicode_Check(pyObject))
870 	{
871 		char* name = const_cast<char*>("");
872 		if (!PyArg_Parse(pyObject, "es", "utf-8", &name))
873 			return nullptr;
874 		QString itemName = QString::fromUtf8(name);
875 		if (!itemName.isEmpty())
876 			itemNames.append(itemName);
877 	}
878 	else if ((pyObject != nullptr) && PyList_Check(pyObject))
879 	{
880 		int len = PyList_Size(pyObject);
881 		for (int i = 0; i < len; ++i)
882 		{
883 			PyObject* pyItem = PyList_GetItem(pyObject, i);
884 			if (!PyUnicode_Check(pyItem))
885 			{
886 				PyErr_SetString(PyExc_TypeError, QObject::tr("incorrect argument: must be a list of strings", "python error").toLocal8Bit().constData());
887 				return nullptr;
888 			}
889 			const char* name = PyUnicode_AsUTF8(pyItem);
890 			QString itemName = QString::fromUtf8(name);
891 			if (itemName.isEmpty())
892 				continue;
893 			itemNames.append(itemName);
894 		}
895 	}
896 
897 	if (!itemNames.isEmpty())
898 	{
899 		QList<PageItem*> pageItems;
900 		pageItems.reserve(itemNames.count());
901 
902 		currentDoc->m_Selection->delaySignalsOn();
903 		currentDoc->m_Selection->clear();
904 		for (int i = 0; i < itemNames.count(); ++i)
905 		{
906 			QString itemName = itemNames.at(i);
907 			PageItem *item = GetUniqueItem(itemName);
908 			if (item == nullptr)
909 				return nullptr;
910 			pageItems.append(item);
911 		}
912 		currentDoc->m_Selection->addItems(pageItems);
913 		currentDoc->m_Selection->delaySignalsOff();
914 	}
915 
916 	if (currentDoc->m_Selection->isEmpty())
917 	{
918 		PyObject* pyList = PyList_New(0);
919 		return pyList;
920 	}
921 
922 	// do the duplicate
923 	currentDoc->itemSelection_Duplicate(0.0, 0.0);
924 
925 	PyObject* pyList = PyList_New(currentDoc->m_Selection->count());
926 	for (int i = 0; i < currentDoc->m_Selection->count(); ++i)
927 	{
928 		PageItem* item = currentDoc->m_Selection->itemAt(i);
929 		PyList_SetItem(pyList, i, PyUnicode_FromString(item->itemName().toUtf8()));
930 	}
931 	return pyList;
932 }
933 
scribus_copyobject(PyObject *,PyObject * args)934 PyObject *scribus_copyobject(PyObject * /* self */, PyObject *args)
935 {
936 	char* name = const_cast<char*>("");
937 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &name))
938 		return nullptr;
939 	if (!checkHaveDocument())
940 		return nullptr;
941 
942 	// Is there a special name given? Yes -> add this to selection
943 	ScribusMainWindow* currentWin = ScCore->primaryMainWindow();
944 	ScribusDoc* currentDoc = currentWin->doc;
945 
946 	PageItem *i = GetUniqueItem(QString::fromUtf8(name));
947 	if (i == nullptr)
948 		return nullptr;
949 	currentDoc->m_Selection->clear();
950 	currentDoc->m_Selection->addItem(i);
951 
952 	// do the copy
953 	currentWin->slotEditCopy();
954 
955 	return PyUnicode_FromString(currentDoc->m_Selection->itemAt(0)->itemName().toUtf8());
956 }
957 
scribus_copyobjects(PyObject *,PyObject * args)958 PyObject *scribus_copyobjects(PyObject * /* self */, PyObject *args)
959 {
960 	PyObject* pyObject = nullptr;
961 	if (!PyArg_ParseTuple(args, "|O", &pyObject))
962 		return nullptr;
963 	if (!checkHaveDocument())
964 		return nullptr;
965 
966 	// Is there a special name given? Yes -> add this to selection
967 	ScribusMainWindow* currentWin = ScCore->primaryMainWindow();
968 	ScribusDoc* currentDoc = currentWin->doc;
969 
970 	if ((pyObject != nullptr) && !PyUnicode_Check(pyObject) && !PyList_Check(pyObject))
971 	{
972 		PyErr_SetString(PyExc_TypeError, QObject::tr("incorrect argument: must be a string or a list of strings", "python error").toLocal8Bit().constData());
973 		return nullptr;
974 	}
975 
976 	QStringList itemNames;
977 	if ((pyObject != nullptr) && PyUnicode_Check(pyObject))
978 	{
979 		char* name = const_cast<char*>("");
980 		if (!PyArg_Parse(pyObject, "es", "utf-8", &name))
981 			return nullptr;
982 		QString itemName = QString::fromUtf8(name);
983 		if (!itemName.isEmpty())
984 			itemNames.append(itemName);
985 	}
986 	else if ((pyObject != nullptr) && PyList_Check(pyObject))
987 	{
988 		int len = PyList_Size(pyObject);
989 		for (int i = 0; i < len; i++)
990 		{
991 			PyObject* pyItem = PyList_GetItem(pyObject, i);
992 			if (!PyUnicode_Check(pyItem))
993 			{
994 				PyErr_SetString(PyExc_TypeError, QObject::tr("incorrect argument: must be a list of strings", "python error").toLocal8Bit().constData());
995 				return nullptr;
996 			}
997 			const char* name = PyUnicode_AsUTF8(pyItem);
998 			QString itemName = QString::fromUtf8(name);
999 			if (itemName.isEmpty())
1000 				continue;
1001 			itemNames.append(itemName);
1002 		}
1003 	}
1004 
1005 	if (!itemNames.isEmpty())
1006 	{
1007 		QList<PageItem*> pageItems;
1008 		pageItems.reserve(itemNames.count());
1009 
1010 		currentDoc->m_Selection->delaySignalsOn();
1011 		currentDoc->m_Selection->clear();
1012 		for (int i = 0; i < itemNames.count(); ++i)
1013 		{
1014 			QString itemName = itemNames.at(i);
1015 			PageItem *item = GetUniqueItem(itemName);
1016 			if (item == nullptr)
1017 				return nullptr;
1018 			pageItems.append(item);
1019 		}
1020 		currentDoc->m_Selection->addItems(pageItems);
1021 		currentDoc->m_Selection->delaySignalsOff();
1022 	}
1023 
1024 	// do the copy
1025 	currentWin->slotEditCopy();
1026 
1027 	Py_RETURN_NONE;
1028 }
1029 
scribus_pasteobject(PyObject *,PyObject *)1030 PyObject *scribus_pasteobject(PyObject * /* self */, PyObject * /*args*/)
1031 {
1032 	if (!checkHaveDocument())
1033 		return nullptr;
1034 
1035 	// do the paste
1036 	ScribusMainWindow* currentWin = ScCore->primaryMainWindow();
1037 	ScribusDoc* currentDoc = currentWin->doc;
1038 	currentWin->slotEditPaste();
1039 	if (!currentDoc->m_Selection->isMultipleSelection())
1040 		return PyUnicode_FromString(currentDoc->m_Selection->itemAt(0)->itemName().toUtf8());
1041 
1042 	QString nameList;
1043 	int docSelectionCount = currentDoc->m_Selection->count();
1044 	for (int i = 0; i < docSelectionCount; ++i)
1045 	{
1046 		nameList.append(currentDoc->m_Selection->itemAt(i)->itemName());
1047 		if (i < docSelectionCount - 1)
1048 			nameList.append(",");
1049 	}
1050 	return PyUnicode_FromString(nameList.toUtf8());
1051 }
1052 
scribus_pasteobjects(PyObject *,PyObject *)1053 PyObject *scribus_pasteobjects(PyObject * /* self */, PyObject * /*args*/)
1054 {
1055 	if (!checkHaveDocument())
1056 		return nullptr;
1057 
1058 	// do the paste
1059 	ScribusMainWindow* currentWin = ScCore->primaryMainWindow();
1060 	ScribusDoc* currentDoc = currentWin->doc;
1061 	currentWin->slotEditPaste();
1062 
1063 	PyObject* pyList = PyList_New(currentDoc->m_Selection->count());
1064 	for (int i = 0; i < currentDoc->m_Selection->count(); ++i)
1065 	{
1066 		PageItem* item = currentDoc->m_Selection->itemAt(i);
1067 		PyList_SetItem(pyList, i, PyUnicode_FromString(item->itemName().toUtf8()));
1068 	}
1069 	return pyList;
1070 }
1071 
1072 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
1073 with header files structure untouched (docstrings are kept near declarations)
1074 PV */
cmdobjdocwarnings()1075 void cmdobjdocwarnings()
1076 {
1077 	QStringList s;
1078 	s << scribus_copyobject__doc__
1079 	  << scribus_copyobjects__doc__
1080 	  << scribus_createbezierline__doc__
1081 	  << scribus_createellipse__doc__
1082 	  << scribus_createimage__doc__
1083 	  << scribus_createline__doc__
1084 	  << scribus_createpathtext__doc__
1085 	  << scribus_createpolygon__doc__
1086 	  << scribus_createpolyline__doc__
1087 	  << scribus_createrect__doc__
1088 	  << scribus_createtable__doc__
1089 	  << scribus_createtext__doc__
1090 	  << scribus_deleteobject__doc__
1091 	  << scribus_duplicateobject__doc__
1092 	  << scribus_duplicateobjects__doc__
1093 	  << scribus_getcharacterstyle__doc__
1094 	  << scribus_getparagraphstyle__doc__
1095 	  << scribus_getstyle__doc__
1096 	  << scribus_gettextflowmode__doc__
1097 	  << scribus_objectexists__doc__
1098 	  << scribus_pasteobject__doc__
1099 	  << scribus_pasteobjects__doc__
1100 	  << scribus_setcharstyle__doc__
1101 	  << scribus_setparagraphstyle__doc__
1102 	  << scribus_setstyle__doc__
1103 	  << scribus_settextflowmode__doc__
1104 	  << scribus_textflowmode__doc__;
1105 }
1106