1 /*
2  * Copyright (C) 2011 Elvis Stansvik <elvstone@gmail.com>
3  *
4  * For general Scribus (>=1.3.2) copyright and licensing information please refer
5  * to the COPYING file provided with the program. Following this notice may exist
6  * a copyright and/or license notice that predates the release of Scribus 1.3.2
7  * for which a new license (GPL+exception) is in place.
8  */
9 
10 #include "cmdtable.h"
11 #include "cmdutil.h"
12 #include "pageitem_table.h"
13 
scribus_gettablerows(PyObject *,PyObject * args)14 PyObject *scribus_gettablerows(PyObject* /* self */, PyObject* args)
15 {
16 	char *Name = const_cast<char*>("");
17 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
18 		return nullptr;
19 	if (!checkHaveDocument())
20 		return nullptr;
21 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
22 	if (i == nullptr)
23 		return nullptr;
24 
25 	PageItem_Table *table = i->asTable();
26 	if (!table)
27 	{
28 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table row count of non-table item.","python error").toLocal8Bit().constData());
29 		return nullptr;
30 	}
31 	return PyLong_FromLong(static_cast<long>(table->rows()));
32 }
33 
scribus_gettablecolumns(PyObject *,PyObject * args)34 PyObject *scribus_gettablecolumns(PyObject* /* self */, PyObject* args)
35 {
36 	char *Name = const_cast<char*>("");
37 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
38 		return nullptr;
39 	if (!checkHaveDocument())
40 		return nullptr;
41 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
42 	if (i == nullptr)
43 		return nullptr;
44 
45 	PageItem_Table *table = i->asTable();
46 	if (!table)
47 	{
48 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table column count of non-table item.","python error").toLocal8Bit().constData());
49 		return nullptr;
50 	}
51 	return PyLong_FromLong(static_cast<long>(table->columns()));
52 }
53 
scribus_inserttablerows(PyObject *,PyObject * args)54 PyObject *scribus_inserttablerows(PyObject* /* self */, PyObject* args)
55 {
56 	char *Name = const_cast<char*>("");
57 	int index, numRows;
58 	if (!PyArg_ParseTuple(args, "ii|es", &index, &numRows, "utf-8", &Name))
59 		return nullptr;
60 	if (!checkHaveDocument())
61 		return nullptr;
62 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
63 	if (i == nullptr)
64 		return nullptr;
65 	PageItem_Table *table = i->asTable();
66 	if (!table)
67 	{
68 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot insert rows on a non-table item.","python error").toLocal8Bit().constData());
69 		return nullptr;
70 	}
71 	if (index < 0 || index > table->rows())
72 	{
73 		PyErr_SetString(PyExc_ValueError, QObject::tr("Table row index out of bounds, must be >= 0 and < %1", "python error").arg(table->rows()).toLocal8Bit().constData());
74 		return nullptr;
75 	}
76 	if (numRows < 1)
77 	{
78 		PyErr_SetString(PyExc_ValueError, QObject::tr("Table row count out of bounds, must be >= 1", "python error").toLocal8Bit().constData());
79 		return nullptr;
80 	}
81 	table->insertRows(index, numRows);
82 	Py_RETURN_NONE;
83 }
84 
scribus_removetablerows(PyObject *,PyObject * args)85 PyObject *scribus_removetablerows(PyObject* /* self */, PyObject* args)
86 {
87 	char *Name = const_cast<char*>("");
88 	int index, numRows;
89 	if (!PyArg_ParseTuple(args, "ii|es", &index, &numRows, "utf-8", &Name))
90 		return nullptr;
91 	if (!checkHaveDocument())
92 		return nullptr;
93 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
94 	if (i == nullptr)
95 		return nullptr;
96 	PageItem_Table *table = i->asTable();
97 	if (!table)
98 	{
99 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot remove rows from a non-table item.","python error").toLocal8Bit().constData());
100 		return nullptr;
101 	}
102 	if (index < 0 || index >= table->rows())
103 	{
104 		PyErr_SetString(PyExc_ValueError, QObject::tr("Table row index out of bounds, must be >= 0 and < %1", "python error").arg(table->rows()).toLocal8Bit().constData());
105 		return nullptr;
106 	}
107 	if (numRows < 1 || numRows >= table->rows())
108 	{
109 		PyErr_SetString(PyExc_ValueError, QObject::tr("Table row count out of bounds, must be >= 1 and < %1", "python error").arg(table->rows()).toLocal8Bit().constData());
110 		return nullptr;
111 	}
112 	if (index + numRows > table->rows())
113 	{
114 		PyErr_SetString(PyExc_ValueError, QObject::tr("Row deletion range out of bounds, index + numRows must be <= %1", "python error").arg(table->rows()).toLocal8Bit().constData());
115 		return nullptr;
116 	}
117 	table->removeRows(index, numRows);
118 	Py_RETURN_NONE;
119 }
120 
scribus_gettablerowheight(PyObject *,PyObject * args)121 PyObject *scribus_gettablerowheight(PyObject* /* self */, PyObject* args)
122 {
123 	char *Name = const_cast<char*>("");
124 	int row;
125 	if (!PyArg_ParseTuple(args, "i|es", &row, "utf-8", &Name))
126 		return nullptr;
127 	if (!checkHaveDocument())
128 		return nullptr;
129 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
130 	if (i == nullptr)
131 		return nullptr;
132 	PageItem_Table *table = i->asTable();
133 	if (!table)
134 	{
135 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get row height from non-table item.","python error").toLocal8Bit().constData());
136 		return nullptr;
137 	}
138 	return PyFloat_FromDouble(static_cast<double>(table->rowHeight(row)));
139 }
140 
scribus_resizetablerow(PyObject *,PyObject * args)141 PyObject *scribus_resizetablerow(PyObject* /* self */, PyObject* args)
142 {
143 	char *Name = const_cast<char*>("");
144 	int row;
145 	double height;
146 	if (!PyArg_ParseTuple(args, "id|es", &row, &height, "utf-8", &Name))
147 		return nullptr;
148 	if (!checkHaveDocument())
149 		return nullptr;
150 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
151 	if (i == nullptr)
152 		return nullptr;
153 	PageItem_Table *table = i->asTable();
154 	if (!table)
155 	{
156 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot resize row on a non-table item.","python error").toLocal8Bit().constData());
157 		return nullptr;
158 	}
159 	if (row < 0 || row >= table->rows())
160 	{
161 		PyErr_SetString(PyExc_ValueError, QObject::tr("Table row index out of bounds, must be >= 0 and < %1", "python error").arg(table->rows()).toLocal8Bit().constData());
162 		return nullptr;
163 	}
164 	if (height <= 0.0)
165 	{
166 		PyErr_SetString(PyExc_ValueError, QObject::tr("Table row height must be > 0.0", "python error").toLocal8Bit().constData());
167 		return nullptr;
168 	}
169 	table->resizeRow(row, height);
170 	Py_RETURN_NONE;
171 }
172 
scribus_inserttablecolumns(PyObject *,PyObject * args)173 PyObject *scribus_inserttablecolumns(PyObject* /* self */, PyObject* args)
174 {
175 	char *Name = const_cast<char*>("");
176 	int index, numColumns;
177 	if (!PyArg_ParseTuple(args, "ii|es", &index, &numColumns, "utf-8", &Name))
178 		return nullptr;
179 	if (!checkHaveDocument())
180 		return nullptr;
181 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
182 	if (i == nullptr)
183 		return nullptr;
184 	PageItem_Table *table = i->asTable();
185 	if (!table)
186 	{
187 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot insert columns on a non-table item.","python error").toLocal8Bit().constData());
188 		return nullptr;
189 	}
190 	if (index < 0 || index > table->columns())
191 	{
192 		PyErr_SetString(PyExc_ValueError, QObject::tr("Table column index out of bounds, must be >= 0 and < %1", "python error").arg(table->columns()).toLocal8Bit().constData());
193 		return nullptr;
194 	}
195 	if (numColumns < 1)
196 	{
197 		PyErr_SetString(PyExc_ValueError, QObject::tr("Table column count out of bounds, must be >= 1", "python error").toLocal8Bit().constData());
198 		return nullptr;
199 	}
200 	table->insertColumns(index, numColumns);
201 	Py_RETURN_NONE;
202 }
203 
scribus_removetablecolumns(PyObject *,PyObject * args)204 PyObject *scribus_removetablecolumns(PyObject* /* self */, PyObject* args)
205 {
206 	char *Name = const_cast<char*>("");
207 	int index, numColumns;
208 	if (!PyArg_ParseTuple(args, "ii|es", &index, &numColumns, "utf-8", &Name))
209 		return nullptr;
210 	if (!checkHaveDocument())
211 		return nullptr;
212 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
213 	if (i == nullptr)
214 		return nullptr;
215 	PageItem_Table *table = i->asTable();
216 	if (!table)
217 	{
218 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot remove columns from a non-table item.","python error").toLocal8Bit().constData());
219 		return nullptr;
220 	}
221 	if (index < 0 || index >= table->columns())
222 	{
223 		PyErr_SetString(PyExc_ValueError, QObject::tr("Table column index out of bounds, must be >= 0 and < %1", "python error").arg(table->columns()).toLocal8Bit().constData());
224 		return nullptr;
225 	}
226 	if (numColumns < 1 || numColumns >= table->columns())
227 	{
228 		PyErr_SetString(PyExc_ValueError, QObject::tr("Table column count out of bounds, must be >= 1 and < %1", "python error").arg(table->columns()).toLocal8Bit().constData());
229 		return nullptr;
230 	}
231 	if (index + numColumns > table->columns())
232 	{
233 		PyErr_SetString(PyExc_ValueError, QObject::tr("Column deletion range out of bounds, index + numColumns must be <= %1", "python error").arg(table->columns()).toLocal8Bit().constData());
234 		return nullptr;
235 	}
236 	table->removeColumns(index, numColumns);
237 	Py_RETURN_NONE;
238 }
239 
scribus_gettablecolumnwidth(PyObject *,PyObject * args)240 PyObject *scribus_gettablecolumnwidth(PyObject* /* self */, PyObject* args)
241 {
242 	char *Name = const_cast<char*>("");
243 	int column;
244 	if (!PyArg_ParseTuple(args, "i|es", &column, "utf-8", &Name))
245 		return nullptr;
246 	if (!checkHaveDocument())
247 		return nullptr;
248 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
249 	if (i == nullptr)
250 		return nullptr;
251 	PageItem_Table *table = i->asTable();
252 	if (!table)
253 	{
254 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get column width from non-table item.","python error").toLocal8Bit().constData());
255 		return nullptr;
256 	}
257 	return PyFloat_FromDouble(static_cast<double>(table->columnWidth(column)));
258 }
259 
scribus_resizetablecolumn(PyObject *,PyObject * args)260 PyObject *scribus_resizetablecolumn(PyObject* /* self */, PyObject* args)
261 {
262 	char *Name = const_cast<char*>("");
263 	int column;
264 	double width;
265 	if (!PyArg_ParseTuple(args, "id|es", &column, &width, "utf-8", &Name))
266 		return nullptr;
267 	if (!checkHaveDocument())
268 		return nullptr;
269 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
270 	if (i == nullptr)
271 		return nullptr;
272 	PageItem_Table *table = i->asTable();
273 	if (!table)
274 	{
275 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot resize column on a non-table item.","python error").toLocal8Bit().constData());
276 		return nullptr;
277 	}
278 	if (column < 0 || column >= table->columns())
279 	{
280 		PyErr_SetString(PyExc_ValueError, QObject::tr("Table column index out of bounds, must be >= 0 and < %1", "python error").arg(table->columns()).toLocal8Bit().constData());
281 		return nullptr;
282 	}
283 	if (width <= 0.0)
284 	{
285 		PyErr_SetString(PyExc_ValueError, QObject::tr("Table column width must be > 0.0", "python error").toLocal8Bit().constData());
286 		return nullptr;
287 	}
288 	table->resizeColumn(column, width);
289 	Py_RETURN_NONE;
290 }
291 
scribus_mergetablecells(PyObject *,PyObject * args)292 PyObject *scribus_mergetablecells(PyObject* /* self */, PyObject* args)
293 {
294 	char *Name = const_cast<char*>("");
295 	int row, column, numRows, numColumns;
296 	if (!PyArg_ParseTuple(args, "iiii|es", &row, &column, &numRows, &numColumns, "utf-8", &Name))
297 		return nullptr;
298 	if (!checkHaveDocument())
299 		return nullptr;
300 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
301 	if (i == nullptr)
302 		return nullptr;
303 	PageItem_Table *table = i->asTable();
304 	if (!table)
305 	{
306 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot merge cells on a non-table item.","python error").toLocal8Bit().constData());
307 		return nullptr;
308 	}
309 	if (numRows < 1 || numColumns < 1)
310 	{
311 		PyErr_SetString(PyExc_ValueError, QObject::tr("Number of rows and columns must both be > 0.", "python error").toLocal8Bit().constData());
312 		return nullptr;
313 	}
314 	if (row < 0 || row >= table->rows() || column < 0 || column >= table->columns() ||
315 			row + numRows - 1 < 0 || row + numRows - 1 >= table->rows() ||
316 			column + numColumns - 1 < 0 || column + numColumns - 1 >= table->columns())
317 	{
318 		PyErr_SetString(PyExc_ValueError, QObject::tr("The area %1,%2 %3x%4 is not inside the table.", "python error").arg(row).arg(column).arg(numColumns).arg(numRows).toLocal8Bit().constData());
319 		return nullptr;
320 	}
321 	table->mergeCells(row, column, numRows, numColumns);
322 	Py_RETURN_NONE;
323 }
324 
scribus_gettablestyle(PyObject *,PyObject * args)325 PyObject *scribus_gettablestyle(PyObject* /* self */, PyObject* args)
326 {
327 	char *Name = const_cast<char*>("");
328 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
329 		return nullptr;
330 	if (!checkHaveDocument())
331 		return nullptr;
332 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
333 	if (i == nullptr)
334 		return nullptr;
335 	PageItem_Table *table = i->asTable();
336 	if (!table)
337 	{
338 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table style on a non-table item.","python error").toLocal8Bit().constData());
339 		return nullptr;
340 	}
341 	return PyUnicode_FromString(table->styleName().toUtf8());
342 }
343 
scribus_settablestyle(PyObject *,PyObject * args)344 PyObject *scribus_settablestyle(PyObject* /* self */, PyObject* args)
345 {
346 	char *Name = const_cast<char*>("");
347 	char *style;
348 	if (!PyArg_ParseTuple(args, "es|es", "utf-8", &style, "utf-8", &Name))
349 		return nullptr;
350 	if (!checkHaveDocument())
351 		return nullptr;
352 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
353 	if (i == nullptr)
354 		return nullptr;
355 	PageItem_Table *table = i->asTable();
356 	if (!table)
357 	{
358 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set table style on a non-table item.","python error").toLocal8Bit().constData());
359 		return nullptr;
360 	}
361 	table->setStyle(QString::fromUtf8(style));
362 	Py_RETURN_NONE;
363 }
364 
scribus_gettablefillcolor(PyObject *,PyObject * args)365 PyObject *scribus_gettablefillcolor(PyObject* /* self */, PyObject* args)
366 {
367 	char *Name = const_cast<char*>("");
368 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
369 		return nullptr;
370 	if (!checkHaveDocument())
371 		return nullptr;
372 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
373 	if (i == nullptr)
374 		return nullptr;
375 	PageItem_Table *table = i->asTable();
376 	if (!table)
377 	{
378 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table fill color on a non-table item.","python error").toLocal8Bit().constData());
379 		return nullptr;
380 	}
381 	return PyUnicode_FromString(table->fillColor().toUtf8());
382 }
383 
scribus_settablefillcolor(PyObject *,PyObject * args)384 PyObject *scribus_settablefillcolor(PyObject* /* self */, PyObject* args)
385 {
386 	char *Name = const_cast<char*>("");
387 	char *color;
388 	if (!PyArg_ParseTuple(args, "es|es", "utf-8", &color, "utf-8", &Name))
389 		return nullptr;
390 	if (!checkHaveDocument())
391 		return nullptr;
392 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
393 	if (i == nullptr)
394 		return nullptr;
395 	PageItem_Table *table = i->asTable();
396 	if (!table)
397 	{
398 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set table fill color on a non-table item.","python error").toLocal8Bit().constData());
399 		return nullptr;
400 	}
401 	table->setFillColor(QString::fromUtf8(color));
402 	Py_RETURN_NONE;
403 }
404 
scribus_settableleftborder(PyObject *,PyObject * args)405 PyObject *scribus_settableleftborder(PyObject* /* self */, PyObject* args)
406 {
407 	char *Name = const_cast<char*>("");
408 	PyObject* borderLines;
409 	if (!PyArg_ParseTuple(args, "O|es", &borderLines, "utf-8", &Name))
410 		return nullptr;
411 	if (!checkHaveDocument())
412 		return nullptr;
413 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
414 	if (i == nullptr)
415 		return nullptr;
416 	PageItem_Table *table = i->asTable();
417 	if (!table)
418 	{
419 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set table left border on a non-table item.","python error").toLocal8Bit().constData());
420 		return nullptr;
421 	}
422 
423 	bool ok = false;
424 	TableBorder border = parseBorder(borderLines, &ok);
425 	if (ok)
426 		table->setLeftBorder(border);
427 	else
428 		return nullptr;
429 
430 	Py_RETURN_NONE;
431 }
432 
scribus_settablerightborder(PyObject *,PyObject * args)433 PyObject *scribus_settablerightborder(PyObject* /* self */, PyObject* args)
434 {
435 	char *Name = const_cast<char*>("");
436 	PyObject* borderLines;
437 	if (!PyArg_ParseTuple(args, "O|es", &borderLines, "utf-8", &Name))
438 		return nullptr;
439 	if (!checkHaveDocument())
440 		return nullptr;
441 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
442 	if (i == nullptr)
443 		return nullptr;
444 	PageItem_Table *table = i->asTable();
445 	if (!table)
446 	{
447 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set table right border on a non-table item.","python error").toLocal8Bit().constData());
448 		return nullptr;
449 	}
450 
451 	bool ok = false;
452 	TableBorder border = parseBorder(borderLines, &ok);
453 	if (ok)
454 		table->setRightBorder(border);
455 	else
456 		return nullptr;
457 
458 	Py_RETURN_NONE;
459 }
460 
scribus_settabletopborder(PyObject *,PyObject * args)461 PyObject *scribus_settabletopborder(PyObject* /* self */, PyObject* args)
462 {
463 	char *Name = const_cast<char*>("");
464 	PyObject* borderLines;
465 	if (!PyArg_ParseTuple(args, "O|es", &borderLines, "utf-8", &Name))
466 		return nullptr;
467 	if (!checkHaveDocument())
468 		return nullptr;
469 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
470 	if (i == nullptr)
471 		return nullptr;
472 	PageItem_Table *table = i->asTable();
473 	if (!table)
474 	{
475 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set table top border on a non-table item.","python error").toLocal8Bit().constData());
476 		return nullptr;
477 	}
478 
479 	bool ok = false;
480 	TableBorder border = parseBorder(borderLines, &ok);
481 	if (ok)
482 		table->setTopBorder(border);
483 	else
484 		return nullptr;
485 
486 	Py_RETURN_NONE;
487 }
488 
scribus_settablebottomborder(PyObject *,PyObject * args)489 PyObject *scribus_settablebottomborder(PyObject* /* self */, PyObject* args)
490 {
491 	char *Name = const_cast<char*>("");
492 	PyObject* borderLines;
493 	if (!PyArg_ParseTuple(args, "O|es", &borderLines, "utf-8", &Name))
494 		return nullptr;
495 	if (!checkHaveDocument())
496 		return nullptr;
497 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
498 	if (i == nullptr)
499 		return nullptr;
500 	PageItem_Table *table = i->asTable();
501 	if (!table)
502 	{
503 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set table bottom border on a non-table item.","python error").toLocal8Bit().constData());
504 		return nullptr;
505 	}
506 
507 	bool ok = false;
508 	TableBorder border = parseBorder(borderLines, &ok);
509 	if (ok)
510 		table->setBottomBorder(border);
511 	else
512 		return nullptr;
513 
514 	Py_RETURN_NONE;
515 }
516 
517 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
518 with header files structure untouched (docstrings are kept near declarations)
519 PV */
cmdtabledocwarnings()520 void cmdtabledocwarnings()
521 {
522 	QStringList s;
523 	s << scribus_gettablecolumns__doc__
524 	  << scribus_gettablecolumnwidth__doc__
525 	  << scribus_gettablefillcolor__doc__
526 	  << scribus_gettablerowheight__doc__
527 	  << scribus_gettablerows__doc__
528 	  << scribus_gettablestyle__doc__
529 	  << scribus_inserttablecolumns__doc__
530 	  << scribus_inserttablerows__doc__
531 	  << scribus_mergetablecells__doc__
532 	  << scribus_removetablerows__doc__
533 	  << scribus_removetablecolumns__doc__
534 	  << scribus_resizetablecolumn__doc__
535 	  << scribus_resizetablerow__doc__
536 	  << scribus_settablebottomborder__doc__
537 	  << scribus_settablefillcolor__doc__
538 	  << scribus_settableleftborder__doc__
539 	  << scribus_settablerightborder__doc__
540 	  << scribus_settablestyle__doc__
541 	  << scribus_settabletopborder__doc__;
542 }
543