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 "cmdtext.h"
8
9 #include "appmodes.h"
10 #include "cmdutil.h"
11 #include "hyphenator.h"
12 #include "pageitem_textframe.h"
13 #include "prefsmanager.h"
14 #include "scribuscore.h"
15 #include "scribusdoc.h"
16 #include "scribusview.h"
17 #include "selection.h"
18 #include "util.h"
19
20
21 template<typename T>
22 class ApplyCharstyleHelper
23 {
24 PageItem* m_item;
25 T m_value;
26
27 public:
ApplyCharstyleHelper(PageItem * item,T v)28 ApplyCharstyleHelper(PageItem* item, T v) : m_item(item), m_value(v) {}
29
apply(void (CharStyle::* f)(T),int p,int len)30 void apply(void (CharStyle::*f)(T), int p, int len)
31 {
32 CharStyle cs;
33 (cs.*f)(m_value);
34 if (m_item->HasSel)
35 {
36 int max = qMax(p + len, m_item->itemText.length());
37 for (int i = p; i < max; i++)
38 {
39 if (m_item->itemText.selected(i))
40 m_item->itemText.applyCharStyle(i, 1, cs);
41 }
42 }
43 else
44 {
45 m_item->itemText.applyCharStyle(p, len, cs);
46 }
47 }
48
49 };
50
scribus_getfontsize(PyObject *,PyObject * args)51 PyObject *scribus_getfontsize(PyObject* /* self */, PyObject* args)
52 {
53 char *Name = const_cast<char*>("");
54 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
55 return nullptr;
56 if (!checkHaveDocument())
57 return nullptr;
58 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
59 if (item == nullptr)
60 return nullptr;
61 if (!(item->isTextFrame()) && !(item->isPathText()))
62 {
63 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get font size of non-text frame.","python error").toLocal8Bit().constData());
64 return nullptr;
65 }
66 if (item->HasSel)
67 {
68 for (int i = 0; i < item->itemText.length(); i++)
69 if (item->itemText.selected(i))
70 return PyFloat_FromDouble(static_cast<double>(item->itemText.charStyle(i).fontSize() / 10.0));
71 return nullptr;
72 }
73 return PyFloat_FromDouble(static_cast<double>(item->currentCharStyle().fontSize() / 10.0));
74 }
75
scribus_getfont(PyObject *,PyObject * args)76 PyObject *scribus_getfont(PyObject* /* self */, PyObject* args)
77 {
78 char *Name = const_cast<char*>("");
79 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
80 return nullptr;
81 if (!checkHaveDocument())
82 return nullptr;
83 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
84 if (item == nullptr)
85 return nullptr;
86 if (!(item->isTextFrame()) && !(item->isPathText()))
87 {
88 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get font of non-text frame.","python error").toLocal8Bit().constData());
89 return nullptr;
90 }
91 if (item->HasSel)
92 {
93 for (int i = 0; i < item->itemText.length(); i++)
94 if (item->itemText.selected(i))
95 return PyUnicode_FromString(item->itemText.charStyle(i).font().scName().toUtf8());
96 return nullptr;
97 }
98 return PyUnicode_FromString(item->currentCharStyle().font().scName().toUtf8());
99 }
100
scribus_gettextcolor(PyObject *,PyObject * args)101 PyObject *scribus_gettextcolor(PyObject* /* self */, PyObject* args)
102 {
103 char *Name = const_cast<char*>("");
104 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
105 return nullptr;
106 if (!checkHaveDocument())
107 return nullptr;
108 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
109 if (item == nullptr)
110 return nullptr;
111 if (!(item->isTextFrame()) && !(item->isPathText()))
112 {
113 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get text color of non-text frame.", "python error").toLocal8Bit().constData());
114 return nullptr;
115 }
116 if (item->HasSel)
117 {
118 for (int i = 0; i < item->itemText.length(); ++i)
119 {
120 if (item->itemText.selected(i))
121 return PyUnicode_FromString(item->itemText.charStyle(i).fillColor().toUtf8());
122 }
123 return nullptr;
124 }
125 return PyUnicode_FromString(item->currentCharStyle().fillColor().toUtf8());
126 }
127
scribus_gettextshade(PyObject *,PyObject * args)128 PyObject *scribus_gettextshade(PyObject* /* self */, PyObject* args)
129 {
130 char *Name = const_cast<char*>("");
131 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
132 return nullptr;
133 if (!checkHaveDocument())
134 return nullptr;
135 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
136 if (item == nullptr)
137 return nullptr;
138 if (!(item->isTextFrame()) && !(item->isPathText()))
139 {
140 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get text color of non-text frame.", "python error").toLocal8Bit().constData());
141 return nullptr;
142 }
143 if (item->HasSel)
144 {
145 for (int i = 0; i < item->itemText.length(); ++i)
146 {
147 if (item->itemText.selected(i))
148 return PyLong_FromLong(item->itemText.charStyle(i).fillShade());
149 }
150 return nullptr;
151 }
152 return PyLong_FromLong(item->currentCharStyle().fillShade());
153 }
154
scribus_gettextlength(PyObject *,PyObject * args)155 PyObject *scribus_gettextlength(PyObject* /* self */, PyObject* args)
156 {
157 char *Name = const_cast<char*>("");
158 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
159 return nullptr;
160 if (!checkHaveDocument())
161 return nullptr;
162 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
163 if (item == nullptr)
164 return nullptr;
165 if (!(item->isTextFrame()) && !(item->isPathText()))
166 {
167 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get text size of non-text frame.","python error").toLocal8Bit().constData());
168 return nullptr;
169 }
170 return PyLong_FromLong(static_cast<long>(item->itemText.length()));
171 }
172
scribus_gettextlines(PyObject *,PyObject * args)173 PyObject *scribus_gettextlines(PyObject* /* self */, PyObject* args)
174 {
175 char *Name = const_cast<char*>("");
176 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
177 return nullptr;
178 if (!checkHaveDocument())
179 return nullptr;
180 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
181 if (item == nullptr)
182 return nullptr;
183 if (!(item->isTextFrame()) && !(item->isPathText()))
184 {
185 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get number of lines of non-text frame.","python error").toLocal8Bit().constData());
186 return nullptr;
187 }
188 return PyLong_FromLong(static_cast<long>(item->textLayout.lines()));
189 }
190
scribus_gettextverticalalignment(PyObject *,PyObject * args)191 PyObject *scribus_gettextverticalalignment(PyObject* /* self */, PyObject* args)
192 {
193 char *Name = const_cast<char*>("");
194 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
195 return nullptr;
196 if (!checkHaveDocument())
197 return nullptr;
198 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
199 if (item == nullptr)
200 return nullptr;
201 if (!item->isTextFrame())
202 {
203 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get vertical alignment of non-text frame.", "python error").toLocal8Bit().constData());
204 return nullptr;
205 }
206 return PyLong_FromLong(static_cast<long>(item->verticalAlignment()));
207 }
208
scribus_getcolumns(PyObject *,PyObject * args)209 PyObject *scribus_getcolumns(PyObject* /* self */, PyObject* args)
210 {
211 char *Name = const_cast<char*>("");
212 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
213 return nullptr;
214 if (!checkHaveDocument())
215 return nullptr;
216 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
217 if (item == nullptr)
218 return nullptr;
219 if (!item->isTextFrame())
220 {
221 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get column count of non-text frame.","python error").toLocal8Bit().constData());
222 return nullptr;
223 }
224 return PyLong_FromLong(static_cast<long>(item->m_columns));
225 }
226
scribus_getcolumngap(PyObject *,PyObject * args)227 PyObject *scribus_getcolumngap(PyObject* /* self */, PyObject* args)
228 {
229 char *Name = const_cast<char*>("");
230 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
231 return nullptr;
232 if (!checkHaveDocument())
233 return nullptr;
234 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
235 if (item == nullptr)
236 return nullptr;
237 if (!item->isTextFrame())
238 {
239 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get column gap of non-text frame.", "python error").toLocal8Bit().constData());
240 return nullptr;
241 }
242 return PyFloat_FromDouble(PointToValue(static_cast<double>(item->m_columnGap)));
243 }
244
scribus_getfontfeatures(PyObject *,PyObject * args)245 PyObject *scribus_getfontfeatures(PyObject* /* self */, PyObject* args)
246 {
247 char *Name = const_cast<char*>("");
248 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
249 return nullptr;
250 if (!checkHaveDocument())
251 return nullptr;
252 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
253 if (item == nullptr)
254 return nullptr;
255 if (!(item->isTextFrame()) && !(item->isPathText()))
256 {
257 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get fontfeatures of non-text frame.","python error").toLocal8Bit().constData());
258 return nullptr;
259 }
260 if (item->HasSel)
261 {
262 for (int i = 0; i < item->itemText.length(); i++)
263 if (item->itemText.selected(i))
264 return PyUnicode_FromString(item->itemText.charStyle(i).fontFeatures().toUtf8());
265 return nullptr;
266 }
267 return PyUnicode_FromString(item->currentCharStyle().fontFeatures().toUtf8());
268 }
269
scribus_getfirstlinkedframe(PyObject *,PyObject * args)270 PyObject *scribus_getfirstlinkedframe(PyObject* /* self */, PyObject* args)
271 {
272 char *Name = const_cast<char*>("");
273 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
274 return nullptr;
275 if (!checkHaveDocument())
276 return nullptr;
277 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
278 if (item == nullptr)
279 return nullptr;
280 if (!item->isTextFrame())
281 {
282 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get linked frames of non-text frame.","python error").toLocal8Bit().constData());
283 return nullptr;
284 }
285
286 return PyUnicode_FromString(item->firstInChain()->itemName().toUtf8());
287 }
288
scribus_getlastlinkedframe(PyObject *,PyObject * args)289 PyObject *scribus_getlastlinkedframe(PyObject* /* self */, PyObject* args)
290 {
291 char *Name = const_cast<char*>("");
292 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
293 return nullptr;
294 if (!checkHaveDocument())
295 return nullptr;
296 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
297 if (item == nullptr)
298 return nullptr;
299 if (!item->isTextFrame())
300 {
301 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get linked frames of non-text frame.","python error").toLocal8Bit().constData());
302 return nullptr;
303 }
304
305 return PyUnicode_FromString(item->lastInChain()->itemName().toUtf8());
306 }
307
scribus_getnextlinkedframe(PyObject *,PyObject * args)308 PyObject *scribus_getnextlinkedframe(PyObject* /* self */, PyObject* args)
309 {
310 char *Name = const_cast<char*>("");
311 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
312 return nullptr;
313 if (!checkHaveDocument())
314 return nullptr;
315 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
316 if (item == nullptr)
317 return nullptr;
318 if (!item->isTextFrame())
319 {
320 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get linked frames of non-text frame.","python error").toLocal8Bit().constData());
321 return nullptr;
322 }
323
324 if (item->nextInChain() != nullptr)
325 return PyUnicode_FromString(item->nextInChain()->itemName().toUtf8());
326
327 Py_RETURN_NONE;
328 }
329
scribus_getprevlinkedframe(PyObject *,PyObject * args)330 PyObject *scribus_getprevlinkedframe(PyObject* /* self */, PyObject* args)
331 {
332 char *Name = const_cast<char*>("");
333 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
334 return nullptr;
335 if (!checkHaveDocument())
336 return nullptr;
337 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
338 if (item == nullptr)
339 return nullptr;
340 if (!item->isTextFrame())
341 {
342 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get linked frames of non-text frame.","python error").toLocal8Bit().constData());
343 return nullptr;
344 }
345
346 if (item->prevInChain() != nullptr)
347 return PyUnicode_FromString(item->prevInChain()->itemName().toUtf8());
348
349 Py_RETURN_NONE;
350 }
351
scribus_getfirstlineoffset(PyObject *,PyObject * args)352 PyObject *scribus_getfirstlineoffset(PyObject* /* self */, PyObject* args)
353 {
354 char *Name = const_cast<char*>("");
355 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
356 return nullptr;
357 if (!checkHaveDocument())
358 return nullptr;
359 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
360 if (item == nullptr)
361 return nullptr;
362 if (!item->isTextFrame())
363 {
364 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get first line offset of non-text frame.", "python error").toLocal8Bit().constData());
365 return nullptr;
366 }
367 return PyLong_FromLong(static_cast<long>(item->firstLineOffset()));
368 }
369
scribus_getlinespacing(PyObject *,PyObject * args)370 PyObject *scribus_getlinespacing(PyObject* /* self */, PyObject* args)
371 {
372 char *Name = const_cast<char*>("");
373 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
374 return nullptr;
375 if (!checkHaveDocument())
376 return nullptr;
377 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
378 if (item == nullptr)
379 return nullptr;
380 if (!item->isTextFrame())
381 {
382 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get line space of non-text frame.","python error").toLocal8Bit().constData());
383 return nullptr;
384 }
385 return PyFloat_FromDouble(static_cast<double>(item->currentStyle().lineSpacing()));
386 }
387
scribus_gettextdistances(PyObject *,PyObject * args)388 PyObject *scribus_gettextdistances(PyObject* /* self */, PyObject* args)
389 {
390 char *Name = const_cast<char*>("");
391 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
392 return nullptr;
393 if (!checkHaveDocument())
394 return nullptr;
395 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
396 if (item == nullptr)
397 return nullptr;
398 if (!item->isTextFrame())
399 {
400 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get text distances of non-text frame.","python error").toLocal8Bit().constData());
401 return nullptr;
402 }
403 return Py_BuildValue("(dddd)",
404 PointToValue(item->textToFrameDistLeft()),
405 PointToValue(item->textToFrameDistRight()),
406 PointToValue(item->textToFrameDistTop()),
407 PointToValue(item->textToFrameDistBottom()));
408 }
409
scribus_getframetext(PyObject *,PyObject * args)410 PyObject *scribus_getframetext(PyObject* /* self */, PyObject* args)
411 {
412 char *Name = const_cast<char*>("");
413 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
414 return nullptr;
415 if (!checkHaveDocument())
416 return nullptr;
417 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
418 if (item == nullptr)
419 return nullptr;
420 if (!(item->isTextFrame()) && !(item->isPathText()))
421 {
422 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get text of non-text frame.","python error").toLocal8Bit().constData());
423 return nullptr;
424 }
425
426 const StoryText& story = item->itemText;
427 QString text;
428 text.reserve(story.hasSelection() ? story.selectionLength() : story.length());
429 for (int i = item->firstInFrame(); i <= item->lastInFrame(); ++i)
430 {
431 if (item->HasSel)
432 {
433 if (story.selected(i))
434 text += story.text(i);
435 }
436 else
437 {
438 text += story.text(i);
439 }
440 }
441 return PyUnicode_FromString(text.toUtf8());
442 }
443
scribus_getalltext(PyObject *,PyObject * args)444 PyObject *scribus_getalltext(PyObject* /* self */, PyObject* args)
445 {
446 char *Name = const_cast<char*>("");
447 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
448 return nullptr;
449 if (!checkHaveDocument())
450 return nullptr;
451 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
452 if (item == nullptr)
453 return nullptr;
454 if (!(item->isTextFrame()) && !(item->isPathText()))
455 {
456 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get text of non-text frame.","python error").toLocal8Bit().constData());
457 return nullptr;
458 }
459
460 // collect all chars from a storytext
461 const StoryText& story = item->itemText;
462 QString text;
463 text.reserve(story.hasSelection() ? story.selectionLength() : story.length());
464 for (int i = 0; i < story.length(); i++)
465 {
466 if (item->HasSel)
467 {
468 if (story.selected(i))
469 text += story.text(i);
470 }
471 else
472 {
473 text += story.text(i);
474 }
475 }
476 return PyUnicode_FromString(text.toUtf8());
477 }
478
scribus_settext(PyObject *,PyObject * args)479 PyObject *scribus_settext(PyObject* /* self */, PyObject* args)
480 {
481 char *Name = const_cast<char*>("");
482 char *Text;
483 if (!PyArg_ParseTuple(args, "es|es", "utf-8", &Text, "utf-8", &Name))
484 return nullptr;
485 if (!checkHaveDocument())
486 return nullptr;
487 PageItem *currItem = GetUniqueItem(QString::fromUtf8(Name));
488 if (currItem == nullptr)
489 return nullptr;
490 if (!(currItem->isTextFrame()) && !(currItem->isPathText()))
491 {
492 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set text of non-text frame.","python error").toLocal8Bit().constData());
493 return nullptr;
494 }
495 QString userText = QString::fromUtf8(Text);
496 userText.replace("\r\n", SpecialChars::PARSEP);
497 userText.replace(QChar('\n') , SpecialChars::PARSEP);
498 PyMem_Free(Text);
499 currItem->itemText.clear();
500 currItem->itemText.insertChars(0, userText);
501 currItem->invalidateLayout();
502
503 Py_RETURN_NONE;
504 }
505
scribus_inserttext(PyObject *,PyObject * args)506 PyObject *scribus_inserttext(PyObject* /* self */, PyObject* args)
507 {
508 char *Name = const_cast<char*>("");
509 char *Text;
510 int pos;
511 if (!PyArg_ParseTuple(args, "esi|es", "utf-8", &Text, &pos, "utf-8", &Name))
512 return nullptr;
513 if (!checkHaveDocument())
514 return nullptr;
515 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
516 if (item == nullptr)
517 return nullptr;
518 if (!(item->isTextFrame()) && !(item->isPathText()))
519 {
520 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot insert text into non-text frame.","python error").toLocal8Bit().constData());
521 return nullptr;
522 }
523 QString textData = QString::fromUtf8(Text);
524 textData.replace("\r\n", SpecialChars::PARSEP);
525 textData.replace(QChar('\n') , SpecialChars::PARSEP);
526 PyMem_Free(Text);
527 if ((pos < -1) || (pos > static_cast<int>(item->itemText.length())))
528 {
529 PyErr_SetString(PyExc_IndexError, QObject::tr("Insert index out of bounds.","python error").toLocal8Bit().constData());
530 return nullptr;
531 }
532 if (pos == -1)
533 pos = item->itemText.length();
534 item->itemText.insertChars(pos, textData, true);
535 item->invalidateLayout();
536
537 Py_RETURN_NONE;
538 }
539
scribus_inserthtmltext(PyObject *,PyObject * args)540 PyObject *scribus_inserthtmltext(PyObject* /* self */, PyObject* args)
541 {
542 char *name = const_cast<char*>("");
543 char *file;
544
545 if (!PyArg_ParseTuple(args, "es|es", "utf-8", &file, "utf-8", &name)) {
546 return nullptr;
547 }
548
549 if (!checkHaveDocument()) {
550 return nullptr;
551 }
552
553 PageItem *item = GetUniqueItem(QString::fromUtf8(name));
554 if (item == nullptr) {
555 return nullptr;
556 }
557
558 if (!(item->isTextFrame()) && !(item->isPathText())) {
559 PyErr_SetString(WrongFrameTypeError,
560 QObject::tr("Cannot insert text into non-text frame.",
561 "python error").toLocal8Bit().constData());
562 return nullptr;
563 }
564
565 QString fileName = QString::fromUtf8(file);
566
567 gtGetText gt(ScCore->primaryMainWindow()->doc);
568 gt.launchImporter(-1, fileName, false, QString("utf-8"), false, true, item);
569
570 // FIXME: PyMem_Free() - are any needed??
571 Py_RETURN_NONE;
572 }
573
scribus_layouttext(PyObject *,PyObject * args)574 PyObject *scribus_layouttext(PyObject* /* self */, PyObject* args)
575 {
576 char *Name = const_cast<char*>("");
577 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
578 return nullptr;
579 if (!checkHaveDocument())
580 return nullptr;
581 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
582 if (item == nullptr)
583 return nullptr;
584 if (!item->isTextFrame() && !item->isPathText())
585 {
586 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot layout text of a non-text frame.", "python error").toLocal8Bit().constData());
587 return nullptr;
588 }
589 item->layout();
590
591 Py_RETURN_NONE;
592 }
593
scribus_layouttextchain(PyObject *,PyObject * args)594 PyObject *scribus_layouttextchain(PyObject* /* self */, PyObject* args)
595 {
596 char *Name = const_cast<char*>("");
597 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
598 return nullptr;
599 if (!checkHaveDocument())
600 return nullptr;
601 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
602 if (item == nullptr)
603 return nullptr;
604 if (!item->isTextFrame() && !item->isPathText())
605 {
606 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot layout text chain for a non-text frame.", "python error").toLocal8Bit().constData());
607 return nullptr;
608 }
609
610 if (item->isPathText())
611 {
612 item->layout();
613 Py_RETURN_NONE;
614 }
615
616 PageItem* firstFrame = item->firstInChain();
617 PageItem* nextFrame = firstFrame;
618 while (nextFrame)
619 {
620 nextFrame->layout();
621 nextFrame = nextFrame->nextInChain();
622 }
623
624 Py_RETURN_NONE;
625 }
626
scribus_settextalignment(PyObject *,PyObject * args)627 PyObject *scribus_settextalignment(PyObject* /* self */, PyObject* args)
628 {
629 char *Name = const_cast<char*>("");
630 int alignment;
631 if (!PyArg_ParseTuple(args, "i|es", &alignment, "utf-8", &Name))
632 return nullptr;
633 if (!checkHaveDocument())
634 return nullptr;
635 if ((alignment > 4) || (alignment < 0))
636 {
637 PyErr_SetString(PyExc_ValueError, QObject::tr("Alignment out of range. Use one of the scribus.ALIGN_* constants.","python error").toLocal8Bit().constData());
638 return nullptr;
639 }
640 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
641 if (item == nullptr)
642 return nullptr;
643 if (!item->isTextFrame())
644 {
645 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set text alignment on a non-text frame.","python error").toLocal8Bit().constData());
646 return nullptr;
647 }
648
649 ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
650 int oldAppMode = ScCore->primaryMainWindow()->doc->appMode;
651
652 Selection tmpSelection(nullptr, false);
653 tmpSelection.addItem(item);
654 if (item->HasSel)
655 doc->appMode = modeEdit;
656 doc->itemSelection_SetAlignment(alignment, &tmpSelection);
657 doc->appMode = oldAppMode;
658
659 Py_RETURN_NONE;
660 }
661
scribus_setdirection(PyObject *,PyObject * args)662 PyObject *scribus_setdirection(PyObject* /* self */, PyObject* args)
663 {
664 char *Name = const_cast<char*>("");
665 int direction;
666 if (!PyArg_ParseTuple(args, "i|es", &direction, "utf-8", &Name))
667 return nullptr;
668 if (!checkHaveDocument())
669 return nullptr;
670 if ((direction > 1) || (direction < 0))
671 {
672 PyErr_SetString(PyExc_ValueError, QObject::tr("direction out of range. Use one of the scribus.DIRECTION* constants.","python error").toLocal8Bit().constData());
673 return nullptr;
674 }
675 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
676 if (item == nullptr)
677 return nullptr;
678 if (!item->isTextFrame())
679 {
680 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set text direction on a non-text frame.","python error").toLocal8Bit().constData());
681 return nullptr;
682 }
683
684 ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
685 int oldAppMode = ScCore->primaryMainWindow()->doc->appMode;
686
687 Selection tmpSelection(nullptr, false);
688 tmpSelection.addItem(item);
689 if (item->HasSel)
690 doc->appMode = modeEdit;
691 doc->itemSelection_SetDirection(direction, &tmpSelection);
692 doc->appMode = oldAppMode;
693
694 Py_RETURN_NONE;
695 }
696
scribus_setfontsize(PyObject *,PyObject * args)697 PyObject *scribus_setfontsize(PyObject* /* self */, PyObject* args)
698 {
699 char *Name = const_cast<char*>("");
700 double size;
701 if (!PyArg_ParseTuple(args, "d|es", &size, "utf-8", &Name))
702 return nullptr;
703 if (!checkHaveDocument())
704 return nullptr;
705 if ((size > 512) || (size < 1))
706 {
707 PyErr_SetString(PyExc_ValueError, QObject::tr("Font size out of bounds - must be 1 <= size <= 512.","python error").toLocal8Bit().constData());
708 return nullptr;
709 }
710 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
711 if (item == nullptr)
712 return nullptr;
713
714 if (!item->isTextFrame())
715 {
716 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set font size on a non-text frame.","python error").toLocal8Bit().constData());
717 return nullptr;
718 }
719
720 ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
721 int oldAppMode = ScCore->primaryMainWindow()->doc->appMode;
722
723 Selection tmpSelection(nullptr, false);
724 tmpSelection.addItem(item);
725 if (item->HasSel)
726 doc->appMode = modeEdit;
727 doc->itemSelection_SetFontSize(qRound(size * 10.0), &tmpSelection);
728 doc->appMode = oldAppMode;
729
730 Py_RETURN_NONE;
731 }
732
scribus_setfontfeatures(PyObject *,PyObject * args)733 PyObject *scribus_setfontfeatures(PyObject* /* self */, PyObject* args)
734 {
735 char *Name = const_cast<char*>("");
736 char *fontfeature = const_cast<char*>("");
737 if (!PyArg_ParseTuple(args, "es|es", "utf-8", &fontfeature, "utf-8", &Name))
738 return nullptr;
739 if (!checkHaveDocument())
740 return nullptr;
741
742 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
743 if (item == nullptr)
744 return nullptr;
745
746 if (!item->isTextFrame())
747 {
748 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set font feature on a non-text frame.","python error").toLocal8Bit().constData());
749 return nullptr;
750 }
751
752 ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
753 int oldAppMode = ScCore->primaryMainWindow()->doc->appMode;
754
755 Selection tmpSelection(nullptr, false);
756 tmpSelection.addItem(item);
757 if (item->HasSel)
758 doc->appMode = modeEdit;
759 doc->itemSelection_SetFontFeatures(QString::fromUtf8(fontfeature), &tmpSelection);
760 doc->appMode = oldAppMode;
761
762 Py_RETURN_NONE;
763 }
764
scribus_setfont(PyObject *,PyObject * args)765 PyObject *scribus_setfont(PyObject* /* self */, PyObject* args)
766 {
767 char *Name = const_cast<char*>("");
768 char *Font = const_cast<char*>("");
769 if (!PyArg_ParseTuple(args, "es|es", "utf-8", &Font, "utf-8", &Name))
770 return nullptr;
771 if (!checkHaveDocument())
772 return nullptr;
773 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
774 if (item == nullptr)
775 return nullptr;
776 if (!(item->isTextFrame()) && !(item->isPathText()))
777 {
778 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set font on a non-text frame.","python error").toLocal8Bit().constData());
779 return nullptr;
780 }
781 if (!PrefsManager::instance().appPrefs.fontPrefs.AvailFonts.contains(QString::fromUtf8(Font)))
782 {
783 PyErr_SetString(PyExc_ValueError, QObject::tr("Font not found.", "python error").toLocal8Bit().constData());
784 return nullptr;
785 }
786
787 ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
788 int oldAppMode = ScCore->primaryMainWindow()->doc->appMode;
789
790 Selection tmpSelection(nullptr, false);
791 tmpSelection.addItem(item);
792 if (item->HasSel)
793 doc->appMode = modeEdit;
794 doc->itemSelection_SetFont(QString::fromUtf8(Font), &tmpSelection);
795 doc->appMode = oldAppMode;
796
797 Py_RETURN_NONE;
798 }
799
scribus_setfirstlineoffset(PyObject *,PyObject * args)800 PyObject *scribus_setfirstlineoffset(PyObject* /* self */, PyObject* args)
801 {
802 char *Name = const_cast<char*>("");
803 int offset;
804 if (!PyArg_ParseTuple(args, "i|es", &offset, "utf-8", &Name))
805 return nullptr;
806 if (!checkHaveDocument())
807 return nullptr;
808 if (offset < 0 || offset > (int) FLOPBaselineGrid)
809 {
810 PyErr_SetString(PyExc_ValueError, QObject::tr("First line offset out of bounds, Use one of the scribus.FLOP_* constants.", "python error").toLocal8Bit().constData());
811 return nullptr;
812 }
813 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
814 if (item == nullptr)
815 return nullptr;
816 if (!item->isTextFrame())
817 {
818 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set first line offset on a non-text frame.", "python error").toLocal8Bit().constData());
819 return nullptr;
820 }
821 item->setFirstLineOffset((FirstLineOffsetPolicy) offset);
822 item->update();
823
824 Py_RETURN_NONE;
825 }
826
scribus_setlinespacing(PyObject *,PyObject * args)827 PyObject *scribus_setlinespacing(PyObject* /* self */, PyObject* args)
828 {
829 char *Name = const_cast<char*>("");
830 double w;
831 if (!PyArg_ParseTuple(args, "d|es", &w, "utf-8", &Name))
832 return nullptr;
833 if (!checkHaveDocument())
834 return nullptr;
835 if (w < 0.1)
836 {
837 PyErr_SetString(PyExc_ValueError, QObject::tr("Line space out of bounds, must be >= 0.1.","python error").toLocal8Bit().constData());
838 return nullptr;
839 }
840 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
841 if (item == nullptr)
842 return nullptr;
843 if (!item->isTextFrame())
844 {
845 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set line spacing on a non-text frame.","python error").toLocal8Bit().constData());
846 return nullptr;
847 }
848
849 ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
850 int oldAppMode = ScCore->primaryMainWindow()->doc->appMode;
851
852 Selection tmpSelection(nullptr, false);
853 tmpSelection.addItem(item);
854 if (item->HasSel)
855 doc->appMode = modeEdit;
856 doc->itemSelection_SetLineSpacing(w, &tmpSelection);
857 doc->appMode = oldAppMode;
858
859 Py_RETURN_NONE;
860 }
861
scribus_setlinespacingmode(PyObject *,PyObject * args)862 PyObject *scribus_setlinespacingmode(PyObject* /* self */, PyObject* args)
863 {
864 char *Name = const_cast<char*>("");
865 int w;
866 if (!PyArg_ParseTuple(args, "i|es", &w, "utf-8", &Name))
867 return nullptr;
868 if (!checkHaveDocument())
869 return nullptr;
870 if (w < 0 || w > 3) // Use constants?
871 {
872 PyErr_SetString(PyExc_ValueError, QObject::tr("Line space mode invalid, must be 0, 1 or 2","python error").toLocal8Bit().constData());
873 return nullptr;
874 }
875 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
876 if (item == nullptr)
877 return nullptr;
878 if (!item->isTextFrame())
879 {
880 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set line spacing mode on a non-text frame.","python error").toLocal8Bit().constData());
881 return nullptr;
882 }
883
884 ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
885 int oldAppMode = ScCore->primaryMainWindow()->doc->appMode;
886
887 Selection tmpSelection(nullptr, false);
888 tmpSelection.addItem(item);
889 if (item->HasSel)
890 doc->appMode = modeEdit;
891 doc->itemSelection_SetLineSpacingMode(w, &tmpSelection);
892 doc->appMode = oldAppMode;
893
894 Py_RETURN_NONE;
895 }
896
scribus_settextdistances(PyObject *,PyObject * args)897 PyObject *scribus_settextdistances(PyObject* /* self */, PyObject* args)
898 {
899 char *Name = const_cast<char*>("");
900 double l,r,t,b;
901 if (!PyArg_ParseTuple(args, "dddd|es", &l, &r, &t, &b, "utf-8", &Name))
902 return nullptr;
903 if (!checkHaveDocument())
904 return nullptr;
905 if (l < 0.0 || r < 0.0 || t < 0.0 || b < 0.0)
906 {
907 PyErr_SetString(PyExc_ValueError, QObject::tr("Text distances out of bounds, must be positive.","python error").toLocal8Bit().constData());
908 return nullptr;
909 }
910 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
911 if (item == nullptr)
912 return nullptr;
913 if (!item->isTextFrame())
914 {
915 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set text distances on a non-text frame.","python error").toLocal8Bit().constData());
916 return nullptr;
917 }
918 item->setTextToFrameDist(ValueToPoint(l), ValueToPoint(r), ValueToPoint(t), ValueToPoint(b));
919
920 Py_RETURN_NONE;
921 }
922
scribus_setcolumngap(PyObject *,PyObject * args)923 PyObject *scribus_setcolumngap(PyObject* /* self */, PyObject* args)
924 {
925 char *Name = const_cast<char*>("");
926 double w;
927 if (!PyArg_ParseTuple(args, "d|es", &w, "utf-8", &Name))
928 return nullptr;
929 if (!checkHaveDocument())
930 return nullptr;
931 if (w < 0.0)
932 {
933 PyErr_SetString(PyExc_ValueError, QObject::tr("Column gap out of bounds, must be positive.","python error").toLocal8Bit().constData());
934 return nullptr;
935 }
936 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
937 if (item == nullptr)
938 return nullptr;
939 if (!item->isTextFrame())
940 {
941 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set column gap on a non-text frame.","python error").toLocal8Bit().constData());
942 return nullptr;
943 }
944 item->m_columnGap = ValueToPoint(w);
945
946 Py_RETURN_NONE;
947 }
948
scribus_setcolumns(PyObject *,PyObject * args)949 PyObject *scribus_setcolumns(PyObject* /* self */, PyObject* args)
950 {
951 char *Name = const_cast<char*>("");
952 int w;
953 if (!PyArg_ParseTuple(args, "i|es", &w, "utf-8", &Name))
954 return nullptr;
955 if (!checkHaveDocument())
956 return nullptr;
957 if (w < 1)
958 {
959 PyErr_SetString(PyExc_ValueError, QObject::tr("Column count out of bounds, must be > 1.","python error").toLocal8Bit().constData());
960 return nullptr;
961 }
962 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
963 if (item == nullptr)
964 return nullptr;
965 if (!item->isTextFrame())
966 {
967 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set number of columns on a non-text frame.","python error").toLocal8Bit().constData());
968 return nullptr;
969 }
970 item->m_columns = w;
971
972 Py_RETURN_NONE;
973 }
974
scribus_settextverticalalignment(PyObject *,PyObject * args)975 PyObject *scribus_settextverticalalignment(PyObject* /* self */, PyObject* args)
976 {
977 char *Name = const_cast<char*>("");
978 int alignment;
979 if (!PyArg_ParseTuple(args, "i|es", &alignment, "utf-8", &Name))
980 return nullptr;
981 if (!checkHaveDocument())
982 return nullptr;
983 if (alignment < 0 || alignment > 2)
984 {
985 PyErr_SetString(PyExc_ValueError, QObject::tr("Vertical alignment out of bounds, Use one of the scribus.ALIGNV_* constants.", "python error").toLocal8Bit().constData());
986 return nullptr;
987 }
988 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
989 if (item == nullptr)
990 return nullptr;
991 if (!item->isTextFrame())
992 {
993 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set vertical alignment on a non-text frame.", "python error").toLocal8Bit().constData());
994 return nullptr;
995 }
996 item->setVerticalAlignment(alignment);
997 item->update();
998
999 Py_RETURN_NONE;
1000 }
1001
scribus_selectframetext(PyObject *,PyObject * args)1002 PyObject *scribus_selectframetext(PyObject* /* self */, PyObject* args)
1003 {
1004 char *Name = const_cast<char*>("");
1005 int start, selcount;
1006 if (!PyArg_ParseTuple(args, "ii|es", &start, &selcount, "utf-8", &Name))
1007 return nullptr;
1008 if (!checkHaveDocument())
1009 return nullptr;
1010 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
1011 if (item == nullptr)
1012 return nullptr;
1013
1014 if (!(item->isTextFrame()) && !(item->isPathText()))
1015 {
1016 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot select text in a non-text frame", "python error").toLocal8Bit().constData());
1017 return nullptr;
1018 }
1019 if (selcount < -1)
1020 {
1021 PyErr_SetString(PyExc_IndexError, QObject::tr("Count must be positive, 0 or -1", "python error").toLocal8Bit().constData());
1022 return nullptr;
1023 }
1024
1025 if (start < 0 || (selcount > 0 && ((item->lastInFrame() == -1) || (selcount + start > item->lastInFrame() - item->firstInFrame() + 1))))
1026 {
1027 PyErr_SetString(PyExc_IndexError, QObject::tr("Selection index out of bounds", "python error").toLocal8Bit().constData());
1028 return nullptr;
1029 }
1030 start += item->firstInFrame();
1031 if (selcount == -1)
1032 selcount = item->lastInFrame() + 1 - start;
1033 item->itemText.deselectAll();
1034 if (selcount == 0)
1035 {
1036 item->HasSel = false;
1037 Py_RETURN_NONE;
1038 }
1039 item->itemText.select(start, selcount, true);
1040 item->HasSel = true;
1041
1042 Py_RETURN_NONE;
1043 }
1044
scribus_selecttext(PyObject *,PyObject * args)1045 PyObject *scribus_selecttext(PyObject* /* self */, PyObject* args)
1046 {
1047 char *Name = const_cast<char*>("");
1048 int start, selcount;
1049 if (!PyArg_ParseTuple(args, "ii|es", &start, &selcount, "utf-8", &Name))
1050 return nullptr;
1051 if (!checkHaveDocument())
1052 return nullptr;
1053 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
1054 if (item == nullptr)
1055 return nullptr;
1056 if (selcount == -1)
1057 {
1058 // user wants to select all after the start point -- CR
1059 selcount = item->itemText.length() - start;
1060 if (selcount < 0)
1061 // user passed start that's > text in the frame
1062 selcount = 0;
1063 }
1064 // cr 2005-01-18 fixed off-by-one with end bound that made selecting the last char impossible
1065 if ((start < 0) || ((start + selcount) > static_cast<int>(item->itemText.length())))
1066 {
1067 PyErr_SetString(PyExc_IndexError, QObject::tr("Selection index out of bounds", "python error").toLocal8Bit().constData());
1068 return nullptr;
1069 }
1070 if (!(item->isTextFrame()) && !(item->isPathText()))
1071 {
1072 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot select text in a non-text frame", "python error").toLocal8Bit().constData());
1073 return nullptr;
1074 }
1075 /* FIXME: not sure if we should make this check or not
1076 if (start > ende)
1077 {
1078 PyErr_SetString(PyExc_ValueError, QString("Selection start > selection end").toLocal8Bit().constData());
1079 return nullptr;
1080 }
1081 */
1082 item->itemText.deselectAll();
1083 if (selcount == 0)
1084 {
1085 item->HasSel = false;
1086 Py_RETURN_NONE;
1087 }
1088 item->itemText.select(start, selcount, true);
1089 item->HasSel = true;
1090
1091 Py_RETURN_NONE;
1092 }
1093
scribus_deletetext(PyObject *,PyObject * args)1094 PyObject *scribus_deletetext(PyObject* /* self */, PyObject* args)
1095 {
1096 char *Name = const_cast<char*>("");
1097 if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
1098 return nullptr;
1099 if (!checkHaveDocument())
1100 return nullptr;
1101 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
1102 if (item == nullptr)
1103 return nullptr;
1104 if (!item->isTextFrame() && !item->isPathText())
1105 {
1106 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot delete text from a non-text frame.","python error").toLocal8Bit().constData());
1107 return nullptr;
1108 }
1109 PageItem_TextFrame* tf_item = item->asTextFrame();
1110 if (tf_item)
1111 {
1112 if (tf_item->HasSel)
1113 tf_item->deleteSelectedTextFromFrame();
1114 else
1115 tf_item->itemText.clear();
1116 }
1117 else
1118 {
1119 //Path text cannot have selected text, :( FIXME
1120 if (item->isPathText())
1121 item->itemText.clear();
1122 }
1123 Py_RETURN_NONE;
1124 }
1125
scribus_settextfill(PyObject *,PyObject * args)1126 PyObject *scribus_settextfill(PyObject* /* self */, PyObject* args)
1127 {
1128 char *Name = const_cast<char*>("");
1129 char *Color;
1130 if (!PyArg_ParseTuple(args, "es|es", "utf-8", &Color, "utf-8", &Name))
1131 return nullptr;
1132 if (!checkHaveDocument())
1133 return nullptr;
1134 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
1135 if (item == nullptr)
1136 return nullptr;
1137 if (!item->isTextFrame() && !item->isPathText())
1138 {
1139 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set text fill on a non-text frame.","python error").toLocal8Bit().constData());
1140 return nullptr;
1141 }
1142 ApplyCharstyleHelper<QString>(item, QString::fromUtf8(Color)).apply(&CharStyle::setFillColor, 0, item->itemText.length());
1143 Py_RETURN_NONE;
1144 }
1145
scribus_settextstroke(PyObject *,PyObject * args)1146 PyObject *scribus_settextstroke(PyObject* /* self */, PyObject* args)
1147 {
1148 char *Name = const_cast<char*>("");
1149 char *Color;
1150 if (!PyArg_ParseTuple(args, "es|es", "utf-8", &Color, "utf-8", &Name))
1151 return nullptr;
1152 if (!checkHaveDocument())
1153 return nullptr;
1154 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
1155 if (item == nullptr)
1156 return nullptr;
1157 if (!item->isTextFrame() && !item->isPathText())
1158 {
1159 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set text stroke on a non-text frame.","python error").toLocal8Bit().constData());
1160 return nullptr;
1161 }
1162 ApplyCharstyleHelper<QString>(item, QString::fromUtf8(Color)).apply(&CharStyle::setStrokeColor, 0, item->itemText.length());
1163 Py_RETURN_NONE;
1164 }
1165
1166
scribus_settextscalingh(PyObject *,PyObject * args)1167 PyObject *scribus_settextscalingh(PyObject* /* self */, PyObject* args)
1168 {
1169 char *Name = const_cast<char*>("");
1170 double sc;
1171 if (!PyArg_ParseTuple(args, "d|es", &sc, "utf-8", &Name))
1172 return nullptr;
1173 if (!checkHaveDocument())
1174 return nullptr;
1175 if (sc < 10)
1176 {
1177 PyErr_SetString(PyExc_ValueError, QObject::tr("Character scaling out of bounds, must be >= 10","python error").toLocal8Bit().constData());
1178 return nullptr;
1179 }
1180 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
1181 if (item == nullptr)
1182 return nullptr;
1183 if (!item->isTextFrame())
1184 {
1185 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set character scaling on a non-text frame.","python error").toLocal8Bit().constData());
1186 return nullptr;
1187 }
1188
1189 ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
1190 int oldAppMode = ScCore->primaryMainWindow()->doc->appMode;
1191
1192 Selection tmpSelection(nullptr, false);
1193 tmpSelection.addItem(item);
1194 if (item->HasSel)
1195 doc->appMode = modeEdit;
1196 doc->itemSelection_SetScaleH(qRound(sc * 10), &tmpSelection);
1197 doc->appMode = oldAppMode;
1198
1199 Py_RETURN_NONE;
1200 }
1201
1202
scribus_settextscalingv(PyObject *,PyObject * args)1203 PyObject *scribus_settextscalingv(PyObject* /* self */, PyObject* args)
1204 {
1205 char *Name = const_cast<char*>("");
1206 double sc;
1207 if (!PyArg_ParseTuple(args, "d|es", &sc, "utf-8", &Name))
1208 return nullptr;
1209 if (!checkHaveDocument())
1210 return nullptr;
1211 if (sc < 10)
1212 {
1213 PyErr_SetString(PyExc_ValueError, QObject::tr("Character scaling out of bounds, must be >= 10","python error").toLocal8Bit().constData());
1214 return nullptr;
1215 }
1216 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
1217 if (item == nullptr)
1218 return nullptr;
1219 if (!item->isTextFrame())
1220 {
1221 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set character scaling on a non-text frame.","python error").toLocal8Bit().constData());
1222 return nullptr;
1223 }
1224
1225 ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
1226 int oldAppMode = ScCore->primaryMainWindow()->doc->appMode;
1227
1228 Selection tmpSelection(nullptr, false);
1229 tmpSelection.addItem(item);
1230 if (item->HasSel)
1231 doc->appMode = modeEdit;
1232 doc->itemSelection_SetScaleV(qRound(sc * 10), &tmpSelection);
1233 doc->appMode = oldAppMode;
1234
1235 Py_RETURN_NONE;
1236 }
1237
1238
scribus_settextshade(PyObject *,PyObject * args)1239 PyObject *scribus_settextshade(PyObject* /* self */, PyObject* args)
1240 {
1241 char *Name = const_cast<char*>("");
1242 int w;
1243 if (!PyArg_ParseTuple(args, "i|es", &w, "utf-8", &Name))
1244 return nullptr;
1245 if (!checkHaveDocument())
1246 return nullptr;
1247 if ((w < 0) || (w > 100))
1248 Py_RETURN_NONE;
1249
1250 PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
1251 if (item == nullptr)
1252 return nullptr;
1253 if (!item->isTextFrame() && !item->isPathText())
1254 {
1255 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set text shade on a non-text frame.","python error").toLocal8Bit().constData());
1256 return nullptr;
1257 }
1258 ApplyCharstyleHelper<double>(item, w).apply(&CharStyle::setFillShade, 0, item->itemText.length());
1259 Py_RETURN_NONE;
1260 }
1261
scribus_linktextframes(PyObject *,PyObject * args)1262 PyObject *scribus_linktextframes(PyObject* /* self */, PyObject* args)
1263 {
1264 char *name1;
1265 char *name2;
1266
1267 if (!PyArg_ParseTuple(args, "eses", "utf-8", &name1, "utf-8", &name2))
1268 return nullptr;
1269 if (!checkHaveDocument())
1270 return nullptr;
1271 PageItem *fromitem = GetUniqueItem(QString::fromUtf8(name1));
1272 if (fromitem == nullptr)
1273 return nullptr;
1274 PageItem *toitem = GetUniqueItem(QString::fromUtf8(name2));
1275 if (toitem == nullptr)
1276 return nullptr;
1277 if (!(fromitem->isTextFrame()) || !(toitem->isTextFrame()))
1278 {
1279 PyErr_SetString(WrongFrameTypeError, QObject::tr("Can only link text frames.","python error").toLocal8Bit().constData());
1280 return nullptr;
1281 }
1282 /* if (toitem->itemText.length() > 0)
1283 {
1284 PyErr_SetString(ScribusException, QObject::tr("Target frame must be empty.","python error").toLocal8Bit().constData());
1285 return nullptr;
1286 }*/
1287 if (toitem->nextInChain() != nullptr)
1288 {
1289 PyErr_SetString(ScribusException, QObject::tr("Target frame links to another frame.","python error").toLocal8Bit().constData());
1290 return nullptr;
1291 }
1292 if (toitem->prevInChain() != nullptr)
1293 {
1294 PyErr_SetString(ScribusException, QObject::tr("Target frame is linked to by another frame.","python error").toLocal8Bit().constData());
1295 return nullptr;
1296 }
1297 if (toitem == fromitem)
1298 {
1299 PyErr_SetString(ScribusException, QObject::tr("Source and target are the same object.","python error").toLocal8Bit().constData());
1300 return nullptr;
1301 }
1302 // references to the others boxes
1303 fromitem->link(toitem);
1304 ScCore->primaryMainWindow()->view->DrawNew();
1305 // enable 'save icon' stuff
1306 ScCore->primaryMainWindow()->slotDocCh();
1307
1308 Py_RETURN_NONE;
1309 }
1310
scribus_unlinktextframes(PyObject *,PyObject * args)1311 PyObject *scribus_unlinktextframes(PyObject* /* self */, PyObject* args)
1312 {
1313 char *name;
1314 if (!PyArg_ParseTuple(args, "es", "utf-8", &name))
1315 return nullptr;
1316 if (!checkHaveDocument())
1317 return nullptr;
1318 PageItem *item = GetUniqueItem(QString::fromUtf8(name));
1319 if (item == nullptr)
1320 return nullptr;
1321 if (!item->isTextFrame())
1322 {
1323 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot unlink a non-text frame.","python error").toLocal8Bit().constData());
1324 return nullptr;
1325 }
1326 // only linked
1327 if (item->prevInChain() == nullptr)
1328 {
1329 PyErr_SetString(ScribusException, QObject::tr("Object is not a linked text frame, can't unlink.","python error").toLocal8Bit().constData());
1330 return nullptr;
1331 }
1332 /* if (item->NextBox == 0)
1333 {
1334 PyErr_SetString(ScribusException, QObject::tr("Object the last frame in a series, can't unlink. Unlink the previous frame instead.","python error").toLocal8Bit().constData());
1335 return nullptr;
1336 }
1337 */
1338 /* PageItem* nextbox = item->NextBox;
1339
1340 while (nextbox != 0)
1341 {
1342 uint a = nextbox->itemText.count();
1343 for (uint s=0; s<a; ++s)
1344 item->itemText.append(nextbox->itemText.take(0));
1345 nextbox = nextbox->NextBox;
1346 } // while
1347 uint a2 = item->itemText.count();
1348 for (uint s = 0; s < a2; ++s)
1349 item->BackBox->itemText.append(item->itemText.take(0));
1350 */
1351 item->prevInChain()->unlink();
1352 // enable 'save icon' stuff
1353 ScCore->primaryMainWindow()->slotDocCh();
1354 ScCore->primaryMainWindow()->view->DrawNew();
1355
1356 Py_RETURN_NONE;
1357 }
1358
1359 /*
1360 * Convert the selected text frame to outlines.
1361 *
1362 * 2004-09-07 (Craig Ringer)
1363 * 2004-09-14 pv frame type, optional frame name param
1364 */
scribus_outlinetext(PyObject *,PyObject * args)1365 PyObject *scribus_outlinetext(PyObject* /* self */, PyObject* args)
1366 {
1367 char *name = const_cast<char*>("");
1368 if (!PyArg_ParseTuple(args, "|es", "utf-8", &name))
1369 return nullptr;
1370 if (!checkHaveDocument())
1371 return nullptr;
1372 PageItem *item = GetUniqueItem(QString::fromUtf8(name));
1373 if (item == nullptr)
1374 return nullptr;
1375 if (!item->isTextFrame())
1376 {
1377 PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot convert a non-text frame to outlines.","python error").toLocal8Bit().constData());
1378 return nullptr;
1379 }
1380 if (item->invalid)
1381 item->layout();
1382 ScCore->primaryMainWindow()->view->deselectItems(true);
1383 ScCore->primaryMainWindow()->view->selectItem(item);
1384 ScCore->primaryMainWindow()->view->TextToPath();
1385
1386 Py_RETURN_NONE;
1387 }
1388
scribus_istextoverflowing(PyObject * self,PyObject * args,PyObject * kw)1389 PyObject *scribus_istextoverflowing(PyObject * self, PyObject* args, PyObject* kw)
1390 {
1391 int nolinks = 0;
1392 char *name = const_cast<char*>("");
1393 char *kwargs[] = {const_cast<char*>("name"), const_cast<char*>("nolinks"), nullptr};
1394 if (!PyArg_ParseTupleAndKeywords(args, kw, "|esi", kwargs, "utf-8", &name, &nolinks))
1395 return nullptr;
1396 if (!checkHaveDocument())
1397 return nullptr;
1398 PageItem *item = GetUniqueItem(QString::fromUtf8(name));
1399 if (item == nullptr)
1400 return nullptr;
1401 if (!item->isTextFrame())
1402 {
1403 PyErr_SetString(WrongFrameTypeError, QObject::tr("Only text frames can be checked for overflowing", "python error").toLocal8Bit().constData());
1404 return nullptr;
1405 }
1406 /* original solution
1407 if (item->itemText.count() > item->MaxChars)
1408 return PyBool_FromLong(static_cast<long>(true));
1409 return PyBool_FromLong(static_cast<long>(false)); */
1410 /*
1411 uint firstFrame = 0;
1412 if (nolinks)
1413 firstFrame = item->itemText.count();
1414 uint chars = item->itemText.count();
1415 uint maxchars = item->MaxChars;
1416 while (item->NextBox != 0) {
1417 item = item->NextBox;
1418 chars += item->itemText.count();
1419 maxchars += item->MaxChars;
1420 }
1421 // no overrun
1422 if (nolinks)
1423 return PyLong_FromLong(maxchars - firstFrame);
1424
1425 if (maxchars > chars)
1426 return PyLong_FromLong(0);
1427 // number of overrunning letters
1428 return PyLong_FromLong(static_cast<long>(chars - maxchars));
1429 */
1430 // refresh overflow information
1431 item->invalidateLayout();
1432 item->layout();
1433 return PyLong_FromLong(static_cast<long>(item->frameOverflows()));
1434 }
1435
1436 /*
1437 * Does hyphenation on the given text frame.
1438 * 08.12.2007: Joachim Neu
1439 */
scribus_hyphenatetext(PyObject *,PyObject * args)1440 PyObject *scribus_hyphenatetext(PyObject*, PyObject* args)
1441 {
1442 char *name = const_cast<char*>("");
1443 if (!PyArg_ParseTuple(args, "|es", "utf-8", &name))
1444 return nullptr;
1445 if (!checkHaveDocument())
1446 return nullptr;
1447 PageItem *item = GetUniqueItem(QString::fromUtf8(name));
1448 if (item == nullptr)
1449 return nullptr;
1450 if (!item->isTextFrame())
1451 {
1452 PyErr_SetString(WrongFrameTypeError, QObject::tr("Can only hyphenate text frame", "python error").toLocal8Bit().constData());
1453 return nullptr;
1454 }
1455 ScCore->primaryMainWindow()->doc->docHyphenator->slotHyphenate(item);
1456 return PyBool_FromLong(1);
1457 }
1458
1459 /*
1460 * Does dehyphenation on the given text frame.
1461 * 13.12.2007: Joachim Neu
1462 */
scribus_dehyphenatetext(PyObject *,PyObject * args)1463 PyObject *scribus_dehyphenatetext(PyObject*, PyObject* args)
1464 {
1465 char *name = const_cast<char*>("");
1466 if (!PyArg_ParseTuple(args, "|es", "utf-8", &name))
1467 return nullptr;
1468 if (!checkHaveDocument())
1469 return nullptr;
1470 PageItem *item = GetUniqueItem(QString::fromUtf8(name));
1471 if (item == nullptr)
1472 return nullptr;
1473 if (!item->isTextFrame())
1474 {
1475 PyErr_SetString(WrongFrameTypeError, QObject::tr("Can only dehyphenate text frame", "python error").toLocal8Bit().constData());
1476 return nullptr;
1477 }
1478 ScCore->primaryMainWindow()->doc->docHyphenator->slotDeHyphenate(item);
1479 return PyBool_FromLong(1);
1480 }
1481
scribus_setpdfbookmark(PyObject *,PyObject * args)1482 PyObject *scribus_setpdfbookmark(PyObject* /* self */, PyObject* args)
1483 {
1484 char *name = const_cast<char*>("");
1485 bool toggle;
1486 if (!PyArg_ParseTuple(args, "b|es", &toggle, "utf-8", &name))
1487 return nullptr;
1488 if (!checkHaveDocument())
1489 return nullptr;
1490 PageItem *item = GetUniqueItem(QString::fromUtf8(name));
1491 if (item == nullptr)
1492 return nullptr;
1493 if (!item->isTextFrame())
1494 {
1495 PyErr_SetString(WrongFrameTypeError, QObject::tr("Can't set bookmark on a non-text frame", "python error").toLocal8Bit().constData());
1496 return nullptr;
1497 }
1498 if (item->isBookmark == toggle)
1499 Py_RETURN_NONE;
1500 if (toggle)
1501 {
1502 item->setIsAnnotation(false);
1503 ScCore->primaryMainWindow()->AddBookMark(item);
1504 }
1505 else
1506 ScCore->primaryMainWindow()->DelBookMark(item);
1507 item->isBookmark = toggle;
1508
1509 Py_RETURN_NONE;
1510 }
1511
scribus_ispdfbookmark(PyObject *,PyObject * args)1512 PyObject *scribus_ispdfbookmark(PyObject* /* self */, PyObject* args)
1513 {
1514 char *name = const_cast<char*>("");
1515 if (!PyArg_ParseTuple(args, "|es", "utf-8", &name))
1516 return nullptr;
1517 if (!checkHaveDocument())
1518 return nullptr;
1519 PageItem *item = GetUniqueItem(QString::fromUtf8(name));
1520 if (item == nullptr)
1521 return nullptr;
1522 if (!item->isTextFrame())
1523 {
1524 PyErr_SetString(WrongFrameTypeError, QObject::tr("Can't get info from a non-text frame", "python error").toLocal8Bit().constData());
1525 return nullptr;
1526 }
1527 if (item->isBookmark)
1528 return PyBool_FromLong(1);
1529 return PyBool_FromLong(0);
1530 }
1531
1532 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
1533 with header files structure untouched (docstrings are kept near declarations)
1534 PV */
cmdtextdocwarnings()1535 void cmdtextdocwarnings()
1536 {
1537 QStringList s;
1538 s << scribus_dehyphenatetext__doc__
1539 << scribus_deletetext__doc__
1540 << scribus_getalltext__doc__
1541 << scribus_getcolumngap__doc__
1542 << scribus_getcolumns__doc__
1543 << scribus_getfirstlineoffset__doc__
1544 << scribus_getfirstlinkedframe__doc__
1545 << scribus_getfont__doc__
1546 << scribus_getfontfeatures__doc__
1547 << scribus_getfontsize__doc__
1548 << scribus_getframetext__doc__
1549 << scribus_getlastlinkedframe__doc__
1550 << scribus_getlinespacing__doc__
1551 << scribus_getnextlinkedframe__doc__
1552 << scribus_getprevlinkedframe__doc__
1553 << scribus_gettext__doc__ // Deprecated
1554 << scribus_gettextcolor__doc__
1555 << scribus_gettextdistances__doc__
1556 << scribus_gettextlength__doc__
1557 << scribus_gettextlines__doc__
1558 << scribus_gettextshade__doc__
1559 << scribus_gettextverticalalignment__doc__
1560 << scribus_hyphenatetext__doc__
1561 << scribus_inserthtmltext__doc__
1562 << scribus_inserttext__doc__
1563 << scribus_ispdfbookmark__doc__
1564 << scribus_istextoverflowing__doc__
1565 << scribus_layouttext__doc__
1566 << scribus_layouttextchain__doc__
1567 << scribus_linktextframes__doc__
1568 << scribus_outlinetext__doc__
1569 << scribus_selectframetext__doc__
1570 << scribus_selecttext__doc__
1571 << scribus_setcolumngap__doc__
1572 << scribus_setcolumns__doc__
1573 << scribus_setdirection__doc__
1574 << scribus_setfirstlineoffset__doc__
1575 << scribus_setfont__doc__
1576 << scribus_setfontfeatures__doc__
1577 << scribus_setfontsize__doc__
1578 << scribus_setlinespacing__doc__
1579 << scribus_setlinespacingmode__doc__
1580 << scribus_setpdfbookmark__doc__
1581 << scribus_settextdistances__doc__
1582 << scribus_settext__doc__
1583 << scribus_settextalignment__doc__
1584 << scribus_settextfill__doc__
1585 << scribus_settextscalingh__doc__
1586 << scribus_settextscalingv__doc__
1587 << scribus_settextshade__doc__
1588 << scribus_settextstroke__doc__
1589 << scribus_settextverticalalignment__doc__
1590 << scribus_tracetext__doc__
1591 << scribus_unlinktextframes__doc__;
1592 }
1593