View Issue Details

IDProjectCategoryView StatusLast Update
0016093ScribusScripterpublic2020-09-12 16:25
Reporterxavid Assigned To 
PrioritynormalSeverityfeatureReproducibilityN/A
Status newResolutionopen 
Product Version 
Target VersionFixed in Version 
Summary0016093: Add getCharCoordinates() and getMark() functions to the Scripter API
DescriptionAdd two new functions to the Scripter API.

positionToPoint(pos[, name]) lets you get information about where a given character in a text frame is located.
getMark(pos[, name]) lets you get information about a mark in a text frame.

These two additions make it possible to write python scripts to add PDF links based on the content of a text frame.

Patch at https://github.com/scribusproject/scribus/pull/127
TagsNo tags attached.
PatchYes

Activities

ale

2020-04-22 13:49

manager   ~0047549

i've commented in the github ticket.

in short:

- imo positionToPoint is not the best possible name for the python API
- i would go for a getMarks() instead of the proposed getMark()

jghali

2020-04-22 14:34

administrator   ~0047553

Yep, positionToPoint() should be indeed renamed. The proposed getCharPosition() on GitHub would be much better.

xavid

2020-04-22 15:10

reporter   ~0047555

Renamed to getCharPosition().

For my use case, I prefer an individual getMark() method because I'm already selectively looking for specific text in my python script to linkify. If people think a getMarks() method would be useful in general, I could add one as well, but I'm not sure if there's a better way to implement it in the C++ than calling StoryText::mark() on each position in turn.

jghali

2020-04-23 23:57

administrator   ~0047557

I would simplify the char index check in getCharCoordinates() : using PageItem 's firstInFrame() or lastInFrame() make the function depends on the state of text layout. During a script execution, this state is usually undefined unless the user calls himself layoutText() or layoutTextChain(). So i would reduce the range check for character index simply to :
if ((pos < 0) || (pos >= item.itemText.length())

Btw, once these discussions are finished, can someone generate a proper patch from GitHub so we can apply it in SVN?

xavid

2020-04-24 02:53

reporter   ~0047558

@jghali: That's how I originally had it, however aoloe in a github comment encouraged me to change it to work with a linked text frame that's not the first, and that's how I did that. I think this function inherently depends on the text layout, because if the text hasn't been laid out then characters won't have meaningful coordinates. I'm happy to change it back if necessary, but this works in practice in my testing.

jghali

2020-04-24 03:44

administrator   ~0047560

@xavid: itemText internal data is shared between all frames of a text chain, so the modified check does not prevent the code to work with linked text frames.

xavid

2020-04-24 04:22

reporter   ~0047561

I guess the challenge there is that normally, methods in the Scripter API use coordinates based on the current page. But if you can get coordinates based on some frame with the same story text as the current frame but on a different page, then you need to also indicate what page the character's on in the return value. That's one reason limiting the scope to a single frame at a time seemed to make sense.

If you want me to do pos based on the overall storytext and add a page to the return value, that seems theoretically reasonable, but I'm not sure how to get the right frame to determine the page and coordinates from when it's different from the selected frame.

jghali

2020-04-24 10:45

administrator   ~0047562

Fyi ScribusDoc has a textCanvasPosition() methods which allows to get the canvas position of a char in a text chain. PageItem has also a frameOfChar() method which allows to get the frame which display a specific char in a text chain.

ale

2020-04-24 14:22

manager   ~0047563

personally, i don't really care if the getCharPosition() only accepts character in the same frame or not.

but it should imo be clear

- what the coordinates refer to (so that you can build a link) and
- what happens when the character is in the overflowing part of the frame.

the simplest solution is probably to check for the character to be in the visible part of the current frame. but if there are better and/or more flexible options, that will make me happy!

xavid

2020-04-24 16:03

reporter   ~0047564

Thanks jghali, used frameOfChar() to make this work for the whole storytext, and now report what page the character's on as well.

xavid

2020-05-12 18:24

reporter   ~0047616

> can someone generate a proper patch from GitHub so we can apply it in SVN?

Are there instructions for this, or what format should the patch be?

ale

2020-05-12 20:03

manager   ~0047617

just upload the diff file you get when you add .diff to the pull request in github:

https://patch-diff.githubusercontent.com/raw/scribusproject/scribus/pull/127.diff

i'll let you do it, so you can make sure that the current state is what should go into scribus.

xavid

2020-05-22 19:28

reporter  

127.diff (6,374 bytes)
diff --git a/scribus/plugins/scriptplugin/cmdtext.cpp b/scribus/plugins/scriptplugin/cmdtext.cpp
index d27e31bd99..6bc8f5bf5f 100644
--- a/scribus/plugins/scriptplugin/cmdtext.cpp
+++ b/scribus/plugins/scriptplugin/cmdtext.cpp
@@ -1354,6 +1354,74 @@ PyObject *scribus_ispdfbookmark(PyObject* /* self */, PyObject* args)
 	return PyBool_FromLong(0);
 }
 
+PyObject *scribus_getcharcoordinates(PyObject* /* self */, PyObject* args)
+{
+	int pos;
+	char *Name = const_cast<char*>("");
+	if (!PyArg_ParseTuple(args, "i|es", &pos, "utf-8", &Name))
+		return nullptr;
+	if (!checkHaveDocument())
+		return nullptr;
+	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
+	if (item == nullptr)
+		return nullptr;
+	if (!(item->isTextFrame()) && !(item->isPathText()))
+	{
+		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get character positions from a non-text frame.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	if ((pos < 0) || (pos >= static_cast<int>(item->itemText.length())))
+	{
+		PyErr_SetString(PyExc_IndexError, QObject::tr("Character index out of bounds.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	// When chaining the frame the char is in doesn't necessarily match
+	// the selected frame.
+	PageItem* actual = item->frameOfChar(pos);
+	if (actual == nullptr) {
+		PyErr_SetString(PyExc_IndexError, QObject::tr("Character index not visible in a frame.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	QLineF box = actual->textLayout.positionToPoint(pos);
+	return Py_BuildValue("(idddd)",
+			     // Scripter API page starts at 1, not 0.
+			     actual->OwnPage + 1,
+			     docUnitXToPageX(actual->xPos() + box.x1()),
+			     docUnitYToPageY(actual->yPos() + box.y1()),
+			     PointToValue(box.x2() - box.x1()),
+			     PointToValue(box.y2() - box.y1()));
+}
+
+PyObject *scribus_getmark(PyObject* /* self */, PyObject* args)
+{
+	int pos;
+	char *Name = const_cast<char*>("");
+	if (!PyArg_ParseTuple(args, "i|es", &pos, "utf-8", &Name))
+		return nullptr;
+	if (!checkHaveDocument())
+		return nullptr;
+	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
+	if (item == nullptr)
+		return nullptr;
+	if (!(item->isTextFrame()) && !(item->isPathText()))
+	{
+		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get mark info from a non-text frame.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	if ((pos < 0) || (pos >= static_cast<int>(item->itemText.length())))
+	{
+		PyErr_SetString(PyExc_IndexError, QObject::tr("Character index out of bounds.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	Mark* mark = item->itemText.mark(pos);
+	if (mark) {
+	  return Py_BuildValue("(is)", mark->getType(),
+			       mark->getData().strtxt.toUtf8().data());
+	} else {
+	  return Py_BuildValue("(is)", MARKNoType, "");
+	}
+}
+
 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
 with header files structure untouched (docstrings are kept near declarations)
 PV */
@@ -1370,6 +1438,7 @@ void cmdtextdocwarnings()
 	  << scribus_getfontsize__doc__
 	  << scribus_getframetext__doc__
 	  << scribus_getlinespace__doc__
+	  << scribus_getmark__doc__
 	  << scribus_gettext__doc__ // Deprecated
 	  << scribus_gettextcolor__doc__
 	  << scribus_gettextdistances__doc__
@@ -1386,6 +1455,7 @@ void cmdtextdocwarnings()
 	  << scribus_layouttextchain__doc__
 	  << scribus_linktextframes__doc__
 	  << scribus_outlinetext__doc__
+	  << scribus_getcharcoordinates__doc__
 	  << scribus_selecttext__doc__
 	  << scribus_setalign__doc__
 	  << scribus_setcolumngap__doc__
diff --git a/scribus/plugins/scriptplugin/cmdtext.h b/scribus/plugins/scriptplugin/cmdtext.h
index bad04bbad8..3a0f5cbe4c 100644
--- a/scribus/plugins/scriptplugin/cmdtext.h
+++ b/scribus/plugins/scriptplugin/cmdtext.h
@@ -581,4 +581,30 @@ May raise WrongFrameTypeError if the target frame is not a text frame\n\
 /*! Is PDF bookmark? */
 PyObject *scribus_ispdfbookmark(PyObject * /*self*/, PyObject* args);
 
+/*! docstring */
+PyDoc_STRVAR(scribus_getcharcoordinates__doc__,
+QT_TR_NOOP("getCharCoordinates(pos, [\"name\"]) -> (page,x,y,width,height)\n\
+\n\
+Returns a (page, x, y, width, height) tuple based on the character at\n\
+position \"pos\" in the text frame \"name\". If the text frame is chained\n\
+from another text frame, \"pos\" is based on the overall story text. If\n\
+ \"name\" is not given the currently selected item is used.\n\
+\n\
+Will only work properly if the text has been layed out; you may need to call\n\
+layoutText() or layoutTextChain() first for correct results.\n\
+"));
+/*! Point for glyth at position */
+PyObject *scribus_getcharcoordinates(PyObject * /*self*/, PyObject* args);
+
+/*! docstring */
+PyDoc_STRVAR(scribus_getmark__doc__,
+QT_TR_NOOP("getMark(pos, [\"name\"]) -> (type,text)\n\
+\n\
+Returns a (type, text) tuple for the mark at position pos in object \"name\".\n\
+If \"name\" is not given the currently selected item is used. If there is no\n\
+mark at that position, type is -1.\n\
+"));
+/*! Returns info about mark */
+PyObject *scribus_getmark(PyObject * /*self*/, PyObject* args);
+
 #endif
diff --git a/scribus/plugins/scriptplugin/scriptplugin.cpp b/scribus/plugins/scriptplugin/scriptplugin.cpp
index a9b5497d60..644e8313dd 100644
--- a/scribus/plugins/scriptplugin/scriptplugin.cpp
+++ b/scribus/plugins/scriptplugin/scriptplugin.cpp
@@ -414,6 +414,8 @@ PyMethodDef scribus_methods[] = {
 	{const_cast<char*>("getUnit"), (PyCFunction)scribus_getunit, METH_NOARGS, tr(scribus_getunit__doc__)},
 	{const_cast<char*>("getVGuides"), (PyCFunction)scribus_getVguides, METH_NOARGS, tr(scribus_getVguides__doc__)},
 	{const_cast<char*>("getXFontNames"), (PyCFunction)scribus_xfontnames, METH_NOARGS, tr(scribus_xfontnames__doc__)},
+	{const_cast<char*>("getCharCoordinates"), scribus_getcharcoordinates, METH_VARARGS, tr(scribus_getcharcoordinates__doc__)},
+	{const_cast<char*>("getMark"), scribus_getmark, METH_VARARGS, tr(scribus_getmark__doc__)},
 	{const_cast<char*>("gotoPage"), scribus_gotopage, METH_VARARGS, tr(scribus_gotopage__doc__)},
 	{const_cast<char*>("groupObjects"), (PyCFunction)scribus_groupobj, METH_VARARGS, tr(scribus_groupobj__doc__)},
 	{const_cast<char*>("haveDoc"), (PyCFunction)scribus_havedoc, METH_NOARGS, tr(scribus_havedoc__doc__)},
127.diff (6,374 bytes)

xavid

2020-05-27 04:17

reporter   ~0047641

Updated patch to fix coordinate conversion when the character is not on the current page.

127-2.diff (6,671 bytes)
diff --git a/scribus/plugins/scriptplugin/cmdtext.cpp b/scribus/plugins/scriptplugin/cmdtext.cpp
index d27e31bd99..af3189a256 100644
--- a/scribus/plugins/scriptplugin/cmdtext.cpp
+++ b/scribus/plugins/scriptplugin/cmdtext.cpp
@@ -1354,6 +1354,83 @@ PyObject *scribus_ispdfbookmark(PyObject* /* self */, PyObject* args)
 	return PyBool_FromLong(0);
 }
 
+PyObject *scribus_getcharcoordinates(PyObject* /* self */, PyObject* args)
+{
+	int pos;
+	char *Name = const_cast<char*>("");
+	if (!PyArg_ParseTuple(args, "i|es", &pos, "utf-8", &Name))
+		return nullptr;
+	if (!checkHaveDocument())
+		return nullptr;
+	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
+	if (item == nullptr)
+		return nullptr;
+	if (!(item->isTextFrame()) && !(item->isPathText()))
+	{
+		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get character positions from a non-text frame.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	if ((pos < 0) || (pos >= static_cast<int>(item->itemText.length())))
+	{
+		PyErr_SetString(PyExc_IndexError, QObject::tr("Character index out of bounds.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	// When chaining the frame the char is in doesn't necessarily match
+	// the selected frame.
+	PageItem* actual = item->frameOfChar(pos);
+	if (actual == nullptr) {
+		PyErr_SetString(PyExc_IndexError, QObject::tr("Character index not visible in a frame.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	QLineF box = actual->textLayout.positionToPoint(pos);
+	// Can't use docUnitXToPageX and docUnitYToPageY because it might not
+	// be on the current page.
+	ScPage* actual_page
+	  = ScCore->primaryMainWindow()->doc->Pages->at(actual->OwnPage);
+	double page_x
+	  = PointToValue(actual->xPos() + box.x1() - actual_page->xOffset());
+	double page_y
+	  = PointToValue(actual->yPos() + box.y1() - actual_page->yOffset());
+
+	return Py_BuildValue("(idddd)",
+			     // Scripter API page starts at 1, not 0.
+			     actual->OwnPage + 1,
+			     page_x,
+			     page_y,
+			     PointToValue(box.x2() - box.x1()),
+			     PointToValue(box.y2() - box.y1()));
+}
+
+PyObject *scribus_getmark(PyObject* /* self */, PyObject* args)
+{
+	int pos;
+	char *Name = const_cast<char*>("");
+	if (!PyArg_ParseTuple(args, "i|es", &pos, "utf-8", &Name))
+		return nullptr;
+	if (!checkHaveDocument())
+		return nullptr;
+	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
+	if (item == nullptr)
+		return nullptr;
+	if (!(item->isTextFrame()) && !(item->isPathText()))
+	{
+		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get mark info from a non-text frame.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	if ((pos < 0) || (pos >= static_cast<int>(item->itemText.length())))
+	{
+		PyErr_SetString(PyExc_IndexError, QObject::tr("Character index out of bounds.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	Mark* mark = item->itemText.mark(pos);
+	if (mark) {
+	  return Py_BuildValue("(is)", mark->getType(),
+			       mark->getData().strtxt.toUtf8().data());
+	} else {
+	  return Py_BuildValue("(is)", MARKNoType, "");
+	}
+}
+
 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
 with header files structure untouched (docstrings are kept near declarations)
 PV */
@@ -1370,6 +1447,7 @@ void cmdtextdocwarnings()
 	  << scribus_getfontsize__doc__
 	  << scribus_getframetext__doc__
 	  << scribus_getlinespace__doc__
+	  << scribus_getmark__doc__
 	  << scribus_gettext__doc__ // Deprecated
 	  << scribus_gettextcolor__doc__
 	  << scribus_gettextdistances__doc__
@@ -1386,6 +1464,7 @@ void cmdtextdocwarnings()
 	  << scribus_layouttextchain__doc__
 	  << scribus_linktextframes__doc__
 	  << scribus_outlinetext__doc__
+	  << scribus_getcharcoordinates__doc__
 	  << scribus_selecttext__doc__
 	  << scribus_setalign__doc__
 	  << scribus_setcolumngap__doc__
diff --git a/scribus/plugins/scriptplugin/cmdtext.h b/scribus/plugins/scriptplugin/cmdtext.h
index bad04bbad8..3a0f5cbe4c 100644
--- a/scribus/plugins/scriptplugin/cmdtext.h
+++ b/scribus/plugins/scriptplugin/cmdtext.h
@@ -581,4 +581,30 @@ May raise WrongFrameTypeError if the target frame is not a text frame\n\
 /*! Is PDF bookmark? */
 PyObject *scribus_ispdfbookmark(PyObject * /*self*/, PyObject* args);
 
+/*! docstring */
+PyDoc_STRVAR(scribus_getcharcoordinates__doc__,
+QT_TR_NOOP("getCharCoordinates(pos, [\"name\"]) -> (page,x,y,width,height)\n\
+\n\
+Returns a (page, x, y, width, height) tuple based on the character at\n\
+position \"pos\" in the text frame \"name\". If the text frame is chained\n\
+from another text frame, \"pos\" is based on the overall story text. If\n\
+ \"name\" is not given the currently selected item is used.\n\
+\n\
+Will only work properly if the text has been layed out; you may need to call\n\
+layoutText() or layoutTextChain() first for correct results.\n\
+"));
+/*! Point for glyth at position */
+PyObject *scribus_getcharcoordinates(PyObject * /*self*/, PyObject* args);
+
+/*! docstring */
+PyDoc_STRVAR(scribus_getmark__doc__,
+QT_TR_NOOP("getMark(pos, [\"name\"]) -> (type,text)\n\
+\n\
+Returns a (type, text) tuple for the mark at position pos in object \"name\".\n\
+If \"name\" is not given the currently selected item is used. If there is no\n\
+mark at that position, type is -1.\n\
+"));
+/*! Returns info about mark */
+PyObject *scribus_getmark(PyObject * /*self*/, PyObject* args);
+
 #endif
diff --git a/scribus/plugins/scriptplugin/scriptplugin.cpp b/scribus/plugins/scriptplugin/scriptplugin.cpp
index a9b5497d60..644e8313dd 100644
--- a/scribus/plugins/scriptplugin/scriptplugin.cpp
+++ b/scribus/plugins/scriptplugin/scriptplugin.cpp
@@ -414,6 +414,8 @@ PyMethodDef scribus_methods[] = {
 	{const_cast<char*>("getUnit"), (PyCFunction)scribus_getunit, METH_NOARGS, tr(scribus_getunit__doc__)},
 	{const_cast<char*>("getVGuides"), (PyCFunction)scribus_getVguides, METH_NOARGS, tr(scribus_getVguides__doc__)},
 	{const_cast<char*>("getXFontNames"), (PyCFunction)scribus_xfontnames, METH_NOARGS, tr(scribus_xfontnames__doc__)},
+	{const_cast<char*>("getCharCoordinates"), scribus_getcharcoordinates, METH_VARARGS, tr(scribus_getcharcoordinates__doc__)},
+	{const_cast<char*>("getMark"), scribus_getmark, METH_VARARGS, tr(scribus_getmark__doc__)},
 	{const_cast<char*>("gotoPage"), scribus_gotopage, METH_VARARGS, tr(scribus_gotopage__doc__)},
 	{const_cast<char*>("groupObjects"), (PyCFunction)scribus_groupobj, METH_VARARGS, tr(scribus_groupobj__doc__)},
 	{const_cast<char*>("haveDoc"), (PyCFunction)scribus_havedoc, METH_NOARGS, tr(scribus_havedoc__doc__)},
127-2.diff (6,671 bytes)

xavid

2020-09-12 14:44

reporter   ~0048047

Here's my latest patch, which makes getMark() return a dict and adds a setMarkText() and an updateDocument() method.

Is there anything else I should be doing here?

127-3.diff (11,653 bytes)
diff --git a/scribus/plugins/scriptplugin/cmddoc.cpp b/scribus/plugins/scriptplugin/cmddoc.cpp
index 258314045e..a3f1bfd810 100644
--- a/scribus/plugins/scriptplugin/cmddoc.cpp
+++ b/scribus/plugins/scriptplugin/cmddoc.cpp
@@ -470,6 +470,12 @@ PyObject* scribus_applymasterpage(PyObject* /* self */, PyObject* args)
 	Py_RETURN_NONE;
 }
 
+PyObject* scribus_updatedocument(PyObject* /* self */, PyObject* args)
+{
+  ScCore->primaryMainWindow()->updateDocument();
+  Py_RETURN_NONE;
+}
+
 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
 with header files structure untouched (docstrings are kept near declarations)
 PV */
@@ -499,5 +505,6 @@ void cmddocdocwarnings()
 	  << scribus_setdoctype__doc__ 
 	  << scribus_setinfo__doc__
 	  << scribus_setmargins__doc__
-	  << scribus_setunit__doc__;
+	  << scribus_setunit__doc__
+	  << scribus_updatedocument__doc__;
 }
diff --git a/scribus/plugins/scriptplugin/cmddoc.h b/scribus/plugins/scriptplugin/cmddoc.h
index 110db951af..2625f0300c 100644
--- a/scribus/plugins/scriptplugin/cmddoc.h
+++ b/scribus/plugins/scriptplugin/cmddoc.h
@@ -313,6 +313,13 @@ Apply master page masterPageName on page pageNumber.\n\
 "));
 PyObject* scribus_applymasterpage(PyObject* self, PyObject* args);
 
+PyDoc_STRVAR(scribus_updatedocument__doc__,
+QT_TR_NOOP("updateDocument()\n\
+\n\
+Update the document.\n\
+"));
+PyObject* scribus_updatedocument(PyObject* self, PyObject* args);
+
 #endif
 
 
diff --git a/scribus/plugins/scriptplugin/cmdtext.cpp b/scribus/plugins/scriptplugin/cmdtext.cpp
index 6c3b6dcb9f..4597d2ab83 100644
--- a/scribus/plugins/scriptplugin/cmdtext.cpp
+++ b/scribus/plugins/scriptplugin/cmdtext.cpp
@@ -1402,6 +1402,119 @@ PyObject *scribus_ispdfbookmark(PyObject* /* self */, PyObject* args)
 	return PyBool_FromLong(0);
 }
 
+PyObject *scribus_getcharcoordinates(PyObject* /* self */, PyObject* args)
+{
+	int pos;
+	char *Name = const_cast<char*>("");
+	if (!PyArg_ParseTuple(args, "i|es", &pos, "utf-8", &Name))
+		return nullptr;
+	if (!checkHaveDocument())
+		return nullptr;
+	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
+	if (item == nullptr)
+		return nullptr;
+	if (!(item->isTextFrame()) && !(item->isPathText()))
+	{
+		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get character positions from a non-text frame.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	if ((pos < 0) || (pos >= static_cast<int>(item->itemText.length())))
+	{
+		PyErr_SetString(PyExc_IndexError, QObject::tr("Character index out of bounds.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	// When chaining the frame the char is in doesn't necessarily match
+	// the selected frame.
+	PageItem* actual = item->frameOfChar(pos);
+	if (actual == nullptr) {
+		PyErr_SetString(PyExc_IndexError, QObject::tr("Character index not visible in a frame.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	QLineF box = actual->textLayout.positionToPoint(pos);
+	// Can't use docUnitXToPageX and docUnitYToPageY because it might not
+	// be on the current page.
+	ScPage* actual_page
+	  = ScCore->primaryMainWindow()->doc->Pages->at(actual->OwnPage);
+	double page_x
+	  = PointToValue(actual->xPos() + box.x1() - actual_page->xOffset());
+	double page_y
+	  = PointToValue(actual->yPos() + box.y1() - actual_page->yOffset());
+
+	return Py_BuildValue("(idddd)",
+			     // Scripter API page starts at 1, not 0.
+			     actual->OwnPage + 1,
+			     page_x,
+			     page_y,
+			     PointToValue(box.x2() - box.x1()),
+			     PointToValue(box.y2() - box.y1()));
+}
+
+PyObject *scribus_getmark(PyObject* /* self */, PyObject* args)
+{
+	int pos;
+	char *Name = const_cast<char*>("");
+	if (!PyArg_ParseTuple(args, "i|es", &pos, "utf-8", &Name))
+		return nullptr;
+	if (!checkHaveDocument())
+		return nullptr;
+	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
+	if (item == nullptr)
+		return nullptr;
+	if (!(item->isTextFrame()) && !(item->isPathText()))
+	{
+		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get mark info from a non-text frame.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	if ((pos < 0) || (pos >= static_cast<int>(item->itemText.length())))
+	{
+		PyErr_SetString(PyExc_IndexError, QObject::tr("Character index out of bounds.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	Mark* mark = item->itemText.mark(pos);
+	if (mark) {
+	  return Py_BuildValue(
+	      "{s:i,s:s,s:s}",
+	      "Type", mark->getType(),
+	      "Text", mark->getData().strtxt.toUtf8().data(),
+	      "Label", mark->label.toUtf8().data());
+	} else {
+	  Py_RETURN_NONE;
+	}
+}
+
+PyObject *scribus_setmarktext(PyObject* /* self */, PyObject* args)
+{
+	int pos;
+	char *val = const_cast<char*>("");
+	char *Name = const_cast<char*>("");
+	if (!PyArg_ParseTuple(args, "ies|es", &pos, "utf-8", &val,
+			      "utf-8", &Name))
+		return nullptr;
+	if (!checkHaveDocument())
+		return nullptr;
+	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
+	if (item == nullptr)
+		return nullptr;
+	if (!(item->isTextFrame()) && !(item->isPathText()))
+	{
+		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot set mark text in a non-text frame.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	if ((pos < 0) || (pos >= static_cast<int>(item->itemText.length())))
+	{
+		PyErr_SetString(PyExc_IndexError, QObject::tr("Character index out of bounds.","python error").toLocal8Bit().constData());
+		return nullptr;
+	}
+	Mark* mark = item->itemText.mark(pos);
+	if (!mark) {
+	  PyErr_SetString(PyExc_ValueError, QObject::tr("No mark at that index.","python error").toLocal8Bit().constData());
+	  return nullptr;
+	}
+
+	mark->setString(QString::fromUtf8(val));
+	Py_RETURN_NONE;
+}
+
 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
 with header files structure untouched (docstrings are kept near declarations)
 PV */
@@ -1418,6 +1531,7 @@ void cmdtextdocwarnings()
 	  << scribus_getfontsize__doc__
 	  << scribus_getframetext__doc__
 	  << scribus_getlinespace__doc__
+	  << scribus_getmark__doc__
 	  << scribus_gettext__doc__ // Deprecated
 	  << scribus_gettextcolor__doc__
 	  << scribus_gettextdistances__doc__
@@ -1434,6 +1548,7 @@ void cmdtextdocwarnings()
 	  << scribus_layouttextchain__doc__
 	  << scribus_linktextframes__doc__
 	  << scribus_outlinetext__doc__
+	  << scribus_getcharcoordinates__doc__
 	  << scribus_selectframetext__doc__
 	  << scribus_selecttext__doc__
 	  << scribus_setalign__doc__
@@ -1445,6 +1560,7 @@ void cmdtextdocwarnings()
 	  << scribus_setfontsize__doc__
 	  << scribus_setlinespace__doc__
 	  << scribus_setlinespacemode__doc__
+	  << scribus_setmarktext__doc__
 	  << scribus_setpdfbookmark__doc__
 	  << scribus_settextdistances__doc__
 	  << scribus_settext__doc__
diff --git a/scribus/plugins/scriptplugin/cmdtext.h b/scribus/plugins/scriptplugin/cmdtext.h
index 034aa126f5..7052dc0541 100644
--- a/scribus/plugins/scriptplugin/cmdtext.h
+++ b/scribus/plugins/scriptplugin/cmdtext.h
@@ -602,4 +602,41 @@ May raise WrongFrameTypeError if the target frame is not a text frame\n\
 /*! Is PDF bookmark? */
 PyObject *scribus_ispdfbookmark(PyObject * /*self*/, PyObject* args);
 
+/*! docstring */
+PyDoc_STRVAR(scribus_getcharcoordinates__doc__,
+QT_TR_NOOP("getCharCoordinates(pos, [\"name\"]) -> (page,x,y,width,height)\n\
+\n\
+Returns a (page, x, y, width, height) tuple based on the character at\n\
+position \"pos\" in the text frame \"name\". If the text frame is chained\n\
+from another text frame, \"pos\" is based on the overall story text. If\n\
+ \"name\" is not given the currently selected item is used.\n\
+\n\
+Will only work properly if the text has been layed out; you may need to call\n\
+layoutText() or layoutTextChain() first for correct results.\n\
+"));
+/*! Point for glyth at position */
+PyObject *scribus_getcharcoordinates(PyObject * /*self*/, PyObject* args);
+
+/*! docstring */
+PyDoc_STRVAR(scribus_getmark__doc__,
+QT_TR_NOOP("getMark(pos, [\"name\"]) -> (type,text)\n\
+\n\
+Returns a (type, text) tuple for the mark at position pos in object \"name\".\n\
+If \"name\" is not given the currently selected item is used. If there is no\n\
+mark at that position, type is -1.\n\
+"));
+/*! Returns info about mark */
+PyObject *scribus_getmark(PyObject * /*self*/, PyObject* args);
+
+/*! docstring */
+PyDoc_STRVAR(scribus_setmarktext__doc__,
+QT_TR_NOOP("setMarkText(pos, \"text\", [\"name\"])\n\
+\n\
+Returns a (type, text) tuple for the mark at position pos in object \"name\".\n\
+If \"name\" is not given the currently selected item is used. If there is no\n\
+mark at that position, type is -1.\n\
+"));
+/*! Returns info about mark */
+PyObject *scribus_setmarktext(PyObject * /*self*/, PyObject* args);
+
 #endif
diff --git a/scribus/plugins/scriptplugin/scriptplugin.cpp b/scribus/plugins/scriptplugin/scriptplugin.cpp
index aab82fa3b6..7b5ab29423 100644
--- a/scribus/plugins/scriptplugin/scriptplugin.cpp
+++ b/scribus/plugins/scriptplugin/scriptplugin.cpp
@@ -414,6 +414,8 @@ PyMethodDef scribus_methods[] = {
 	{const_cast<char*>("getUnit"), (PyCFunction)scribus_getunit, METH_NOARGS, tr(scribus_getunit__doc__)},
 	{const_cast<char*>("getVGuides"), (PyCFunction)scribus_getVguides, METH_NOARGS, tr(scribus_getVguides__doc__)},
 	{const_cast<char*>("getXFontNames"), (PyCFunction)scribus_xfontnames, METH_NOARGS, tr(scribus_xfontnames__doc__)},
+	{const_cast<char*>("getCharCoordinates"), scribus_getcharcoordinates, METH_VARARGS, tr(scribus_getcharcoordinates__doc__)},
+	{const_cast<char*>("getMark"), scribus_getmark, METH_VARARGS, tr(scribus_getmark__doc__)},
 	{const_cast<char*>("gotoPage"), scribus_gotopage, METH_VARARGS, tr(scribus_gotopage__doc__)},
 	{const_cast<char*>("groupObjects"), (PyCFunction)scribus_groupobj, METH_VARARGS, tr(scribus_groupobj__doc__)},
 	{const_cast<char*>("haveDoc"), (PyCFunction)scribus_havedoc, METH_NOARGS, tr(scribus_havedoc__doc__)},
@@ -431,6 +433,7 @@ PyMethodDef scribus_methods[] = {
 	{const_cast<char*>("isLocked"), scribus_islocked, METH_VARARGS, tr(scribus_islocked__doc__)},
 	{const_cast<char*>("layoutText"), scribus_layouttext, METH_VARARGS, tr(scribus_layouttext__doc__)},
 	{const_cast<char*>("layoutTextChain"), scribus_layouttextchain, METH_VARARGS, tr(scribus_layouttextchain__doc__)},
+	{const_cast<char*>("updateDocument"), scribus_updatedocument, METH_VARARGS, tr(scribus_updatedocument__doc__)},
 	{const_cast<char*>("linkTextFrames"), scribus_linktextframes, METH_VARARGS, tr(scribus_linktextframes__doc__)},
 	{const_cast<char*>("loadImage"), scribus_loadimage, METH_VARARGS, tr(scribus_loadimage__doc__)},
 	{const_cast<char*>("loadStylesFromFile"), scribus_loadstylesfromfile, METH_VARARGS, tr(scribus_loadstylesfromfile__doc__)},
@@ -538,6 +541,7 @@ PyMethodDef scribus_methods[] = {
 	{const_cast<char*>("setLineWidth"), scribus_setlinewidth, METH_VARARGS, tr(scribus_setlinewidth__doc__)},
 	{const_cast<char*>("setBleeds"), scribus_setbleeds, METH_VARARGS, tr(scribus_setbleeds__doc__)},
 	{const_cast<char*>("setMargins"), scribus_setmargins, METH_VARARGS, tr(scribus_setmargins__doc__)},
+	{const_cast<char*>("setMarkText"), scribus_setmarktext, METH_VARARGS, tr(scribus_setmarktext__doc__)},
 	{const_cast<char*>("setBaseLine"), scribus_setbaseline, METH_VARARGS, tr(scribus_setbaseline__doc__)},
 	{const_cast<char*>("setItemName"), scribus_setitemname, METH_VARARGS, tr(scribus_setitemname__doc__)},
 	{const_cast<char*>("setMultiLine"), scribus_setmultiline, METH_VARARGS, tr(scribus_setmultiline__doc__)},
127-3.diff (11,653 bytes)

Issue History

Date Modified Username Field Change
2020-04-22 04:26 xavid New Issue
2020-04-22 13:49 ale Note Added: 0047549
2020-04-22 14:34 jghali Note Added: 0047553
2020-04-22 15:10 xavid Note Added: 0047555
2020-04-23 23:48 jghali Summary Add positionToPoint() and getMark() functions to the Scripter API => Add getCharCoordinates() and getMark() functions to the Scripter API
2020-04-23 23:57 jghali Note Added: 0047557
2020-04-24 02:53 xavid Note Added: 0047558
2020-04-24 03:44 jghali Note Added: 0047560
2020-04-24 04:22 xavid Note Added: 0047561
2020-04-24 10:45 jghali Note Added: 0047562
2020-04-24 14:22 ale Note Added: 0047563
2020-04-24 16:03 xavid Note Added: 0047564
2020-05-12 18:24 xavid Note Added: 0047616
2020-05-12 20:03 ale Note Added: 0047617
2020-05-22 19:28 xavid File Added: 127.diff
2020-05-27 04:17 xavid File Added: 127-2.diff
2020-05-27 04:17 xavid Note Added: 0047641
2020-09-12 14:44 xavid File Added: 127-3.diff
2020-09-12 14:44 xavid Note Added: 0048047